From c828f10cd2c53b7ff2cc061e73b239973ee17bc6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 13 Jan 2026 18:41:59 +0200 Subject: [PATCH 0001/1058] arm64: dts: qcom: agatti: enable FastRPC on the ADSP On Agatti platform the ADSP provides FastRPC support. Add corresponding device node, in order to be able to utilize the DSP offload from the Linux side. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/agatti.dtsi | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index 8bf5c5583fc22..5756b90e1b3bb 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -2235,6 +2235,47 @@ }; }; }; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + + qcom,non-secure-domain; + + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x1c3 0x0>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x1c4 0x0>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x1c5 0x0>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x1c6 0x0>; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x1c7 0x0>; + }; + }; }; }; From be3e7a4e9a0e14d733662fa8f78e4ebc4af5070a Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 10:00:04 +0800 Subject: [PATCH 0002/1058] QCLINUX: qcom-dcc: Add driver support for Data Capture and Compare unit(DCC) The DCC is a DMA Engine designed to capture and store data during system crash or software triggers. The DCC operates based on user inputs via the debugfs interface. The user gives addresses as inputs and these addresses are stored in the dcc sram. In case of a system crash or a manual software trigger by the user through the debugfs interface, the dcc captures and stores the values at these addresses. This patch contains the driver which has all the methods pertaining to the debugfs interface, auxiliary functions to support all the four fundamental operations of dcc namely read, write, read/modify/write and loop. The probe method here instantiates all the resources necessary for dcc to operate mainly the dedicated dcc sram where it stores the values. The DCC driver can be used for debugging purposes without going for a reboot since it can perform software triggers as well based on user inputs. Also add the documentation for debugfs entries which explains the functionalities of each debugfs file that has been created for dcc. The following is the justification of using debugfs interface over the other alternatives like sysfs/ioctls i) As can be seen from the debugfs attribute descriptions, some of the debugfs attribute files here contains multiple arguments which needs to be accepted from the user. This goes against the design style of sysfs. ii) The user input patterns have been made simple and convenient in this case with the use of debugfs interface as user doesn't need to shuffle between different files to execute one instruction as was the case on using other alternatives. Signed-off-by: Jie Gan --- drivers/misc/Kconfig | 8 + drivers/misc/Makefile | 1 + drivers/misc/qcom-dcc.c | 1610 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1619 insertions(+) create mode 100644 drivers/misc/qcom-dcc.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 5cc79d1517af5..62b73f320df6d 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -309,6 +309,14 @@ config QCOM_FASTRPC applications DSP processor. Say M if you want to enable this module. +config QCOM_DCC + tristate "Qualcomm Technologies, Inc. Data Capture and Compare (DCC) engine driver" + depends on ARCH_QCOM || COMPILE_TEST + help + This option enables the driver for the Data Capture and Compare engine. DCC + driver provides interfaces to configure DCC block and read back the captured + data from the DCC's internal SRAM. The module name for this is qcom-dcc. + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b32a2597d2467..338ed270b7cfc 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -75,3 +75,4 @@ obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ obj-y += amd-sbi/ obj-$(CONFIG_MISC_RP1) += rp1/ +obj-$(CONFIG_QCOM_DCC) += qcom-dcc.o diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c new file mode 100644 index 0000000000000..a511faac5d4b0 --- /dev/null +++ b/drivers/misc/qcom-dcc.c @@ -0,0 +1,1610 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * DCC(Data Capture and Compare) is a DMA engine designed for debugging + * purposes. + * In case of a system crash or manual software triggers by the user the + * DCC hardware stores the value at the register addresses which can be + * used for debugging purposes. + * The DCC driver provides the user with debugfs interface to configure the + * register addresses. The options that the DCC hardware provides include + * reading from registers, writing to registers, first reading and then + * writing to registers and looping through the values of the same + * register. + * + * In certain cases a register write needs to be executed for accessing the + * rest of the registers, also the user might want to record the changing + * values of a register with time for which he has the option to use the + * loop feature. + * + * The options mentioned above are exposed to the user by debugfs files + * once the driver is probed. The details and usage of this debugfs files + * are documented in Documentation/ABI/testing/debugfs-driver-dcc. + * + * As an example let us consider a couple of debug scenarios where DCC has + * been proved to be effective for debugging purposes:- + * + * i)TimeStamp Related Issue + * + * On SC7180, there was a coresight timestamp issue where it would + * occasionally be all 0 instead of proper timestamp values. + * + * Proper timestamp: + * Idx:3373; ID:10; I_TIMESTAMP : Timestamp.; Updated val = + * 0x13004d8f5b7aa; CC=0x9e + * + * Zero timestamp: + * Idx:3387; ID:10; I_TIMESTAMP : Timestamp.; Updated val = 0x0; CC=0xa2 + * + * Now this is a non-fatal issue and doesn't need a system reset, but still + * needs to be rootcaused and fixed for those who do care about coresight + * etm traces. + * Since this is a timestamp issue, we would be looking for any timestamp + * related clocks and such. + * + * We get all the clk register details from IP documentation and configure + * it via DCC config debugfs node. Before that we set the current + * linked list. + * + * Program the linked list with the addresses + * echo R 0x10c004 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c008 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c00c > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c010 > /sys/kernel/debug/qcom-dcc/../3/config + * ..... and so on for other timestamp related clk registers + * + * Other way of specifying is in "addr len" pair, in below case it + * specifies to capture 4 words starting 0x10C004 + * + * echo R 0x10C004 4 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Configuration can be saved to a file and reuse it later. + * cat /sys/kernel/debug/qcom-dcc/../3/config > config_3 + * Post reboot, write the file to config. + * echo config_3 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Enable DCC + * echo 1 > /sys/kernel/debug/qcom-dcc/../3/enable + * + * Run the timestamp test for working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram1.bin + * + * Run the timestamp test for non-working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram2.bin + * + * Get the parser from + * https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/tools/-/tree/opensource-tools.lnx.1.0.r176-rel/dcc_parser + * + * Parse the SRAM bin + * python dcc_parser.py -s dcc_sram1.bin --v2 -o output/ python + * dcc_parser.py -s dcc_sram2.bin --v2 -o output/ + * + * Sample parsed output of dcc_sram1.bin: + * + * + * 03/14/21 + * Linux DCC Parser + * + * + * + * + * + * + * next_ll_offset : 0x1c + * + * ii)NOC register errors + * + * A particular class of registers called NOC which are functional + * registers was reporting errors while logging the values.To trace these + * errors the DCC has been used effectively. + * The steps followed were similar to the ones mentioned above. + * In addition to NOC registers a few other dependent registers were + * configured in DCC to monitor it's values during a crash. A look at the + * dependent register values revealed that the crash was happening due to a + * secured access to one of these dependent registers. + * All these debugging activity and finding the root cause was achieved + * using DCC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STATUS_READY_TIMEOUT 5000 /* microseconds */ + +/* DCC registers */ +#define DCC_HW_INFO 0x04 +#define DCC_LL_NUM_INFO 0x10 +#define DCC_LL_LOCK 0x00 +#define DCC_LL_CFG 0x04 +#define DCC_LL_BASE 0x08 +#define DCC_FD_BASE 0x0c +#define DCC_LL_OFFSET 0x80 +#define DCC_LL_TIMEOUT 0x10 +#define DCC_LL_INT_ENABLE 0x18 +#define DCC_LL_INT_STATUS 0x1c +#define DCC_LL_SW_TRIGGER 0x2c +#define DCC_LL_BUS_ACCESS_STATUS 0x30 + +/* Default value used if a bit 6 in the HW_INFO register is set. */ +#define DCC_FIX_LOOP_OFFSET 16 + +/* Mask to find version info from HW_Info register */ +#define DCC_VER_INFO_MASK BIT(9) + +#define MAX_DCC_OFFSET GENMASK(9, 2) +#define MAX_DCC_LEN GENMASK(6, 0) +#define MAX_LOOP_CNT GENMASK(7, 0) +#define MAX_LOOP_ADDR 10 + +#define DCC_ADDR_DESCRIPTOR 0x00 +#define DCC_ADDR_LIMIT 27 +#define DCC_WORD_SIZE sizeof(u32) +#define DCC_ADDR_RANGE_MASK GENMASK(31, 4) +#define DCC_LOOP_DESCRIPTOR BIT(30) +#define DCC_RD_MOD_WR_DESCRIPTOR BIT(31) +#define DCC_LINK_DESCRIPTOR GENMASK(31, 30) +#define DCC_STATUS_MASK GENMASK(1, 0) +#define DCC_LOCK_MASK BIT(0) +#define DCC_LOOP_OFFSET_MASK BIT(6) +#define DCC_TRIGGER_MASK BIT(9) + +#define DCC_WRITE_MASK BIT(15) +#define DCC_WRITE_OFF_MASK GENMASK(7, 0) +#define DCC_WRITE_LEN_MASK GENMASK(14, 8) + +#define DCC_READ_IND 0x00 +#define DCC_WRITE_IND (BIT(28)) + +#define DCC_AHB_IND 0x00 +#define DCC_APB_IND BIT(29) + +#define DCC_MAX_LINK_LIST 8 + +#define DCC_VER_MASK2 GENMASK(5, 0) + +#define DCC_SRAM_WORD_LENGTH 4 + +#define DCC_RD_MOD_WR_ADDR 0xC105E + +#define MEM_MAP_VER1 0x1 +#define MEM_MAP_VER2 0x2 +#define MEM_MAP_VER3 0x3 + +#define LINE_BUFFER_MAX_SZ 50 +enum dcc_descriptor_type { + DCC_READ_TYPE, + DCC_LOOP_TYPE, + DCC_READ_WRITE_TYPE, + DCC_WRITE_TYPE +}; + +/** + * struct dcc_config_entry - configuration information related to each dcc instruction + * @base: Base address of the register to be configured in dcc + * @offset: Offset to the base address to be configured in dcc + * @len: Length of the address in words of 4 bytes to be configured in dcc + * @loop_cnt: The number of times to loop on the register address in case + of loop instructions + * @write_val: The value to be written on the register address in case of + write instructions + * @mask: Mask corresponding to the value to be written in case of + write instructions + * @apb_bus: Type of bus to be used for the instruction, can be either + 'apb' if 1 or 'ahb' if 0 + * @desc_type: Stores the type of dcc instruction + * @list: This is used to append this instruction to the list of + instructions + */ +struct dcc_config_entry { + u32 base; + u32 offset; + u32 len; + u32 loop_cnt; + u32 write_val; + u32 mask; + bool apb_bus; + enum dcc_descriptor_type desc_type; + struct list_head list; +}; + +/** + * struct dcc_drvdata - configuration information related to a dcc device + * @base: Base Address of the dcc device + * @dev: The device attached to the driver data + * @mutex: Lock to protect access and manipulation of dcc_drvdata + * @ram_base: Base address for the SRAM dedicated for the dcc device + * @ram_size: Total size of the SRAM dedicated for the dcc device + * @ram_offset: Offset to the SRAM dedicated for dcc device + * @ram_cfg: Used for address limit calculation for dcc + * @ram_start: Starting address of DCC SRAM + * @mem_map_ver: Memory map version of DCC hardware + * @sram_dev: Miscellaneous device equivalent of dcc SRAM + * @cfg_head: Points to the head of the linked list of addresses + * @dbg_dir: The dcc debugfs directory under which all the debugfs files are placed + * @max_link_list: Total number of linkedlists supported by the DCC configuration + * @loop_shift: Loop offset bits range for the addresses + * @enable_bitmap: Bitmap to capture the enabled status of each linked list of addresses + */ +struct dcc_drvdata { + void __iomem *base; + void __iomem *ram_base; + struct device *dev; + /* Lock to protect access and manipulation of dcc_drvdata */ + struct mutex mutex; + size_t ram_size; + u32 ram_offset; + unsigned int ram_cfg; + unsigned int ram_start; + u64 mem_map_ver; + struct miscdevice sram_dev; + struct list_head *cfg_head; + struct dentry *dbg_dir; + size_t max_link_list; + u8 loop_shift; + unsigned long *enable_bitmap; + char **temp_buff_ptr; +}; + +struct dcc_cfg_attr { + u32 addr; + u32 prev_addr; + u32 prev_off; + u32 link; + u32 sram_offset; +}; + +struct dcc_cfg_loop_attr { + u32 loop_cnt; + u32 loop_len; + u32 loop_off; + bool loop_start; +}; + +static inline u32 dcc_status(int version) +{ + return version == 1 ? 0x0c : 0x1c; +} + +static inline u32 dcc_list_offset(int version) +{ + if (version == 1) + return 0x1c; + else if (version == 2) + return 0x2c; + else + return 0x34; +} + +static inline void dcc_list_writel(struct dcc_drvdata *drvdata, + u32 val, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + writel(val, drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static inline u32 dcc_list_readl(struct dcc_drvdata *drvdata, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + return readl(drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static void dcc_sram_write_auto(struct dcc_drvdata *drvdata, + u32 val, u32 *off) +{ + /* If the overflow condition is met increment the offset + * and return to indicate that overflow has occurred + */ + if (*off > drvdata->ram_size - 4) { + *off += 4; + return; + } + + writel(val, drvdata->ram_base + *off); + + *off += 4; +} + +static int dcc_sw_trigger(struct dcc_drvdata *drvdata) +{ + void __iomem *addr; + int i; + u32 status; + u32 ll_cfg; + u32 tmp_ll_cfg; + u32 val; + int ret = 0; + + mutex_lock(&drvdata->mutex); + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, 1, i, DCC_LL_SW_TRIGGER); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + } + + addr = drvdata->base + dcc_status(drvdata->mem_map_ver); + if (readl_poll_timeout(addr, val, !FIELD_GET(DCC_STATUS_MASK, val), + 1, STATUS_READY_TIMEOUT)) { + dev_err(drvdata->dev, "DCC is busy after receiving sw trigger\n"); + ret = -EBUSY; + goto out_unlock; + } + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + + status = dcc_list_readl(drvdata, i, DCC_LL_BUS_ACCESS_STATUS); + if (!status) + continue; + + dev_err(drvdata->dev, "Read access error for list %d err: 0x%x\n", + i, status); + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, DCC_STATUS_MASK, i, DCC_LL_BUS_ACCESS_STATUS); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + ret = -ENODATA; + break; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_ll_cfg_reset_link(struct dcc_cfg_attr *cfg) +{ + cfg->addr = 0x00; + cfg->link = 0; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; +} + +static void dcc_emit_read_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); + } + + cfg->addr = DCC_RD_MOD_WR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->mask, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0; +} + +static void dcc_emit_loop(struct dcc_drvdata *drvdata, struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + struct dcc_cfg_loop_attr *cfg_loop, + u32 *total_len) +{ + int loop; + + /* Check if we need to write link of prev entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + if (cfg_loop->loop_start) { + loop = (cfg->sram_offset - cfg_loop->loop_off) / 4; + loop |= (cfg_loop->loop_cnt << drvdata->loop_shift) & + GENMASK(DCC_ADDR_LIMIT, drvdata->loop_shift); + loop |= DCC_LOOP_DESCRIPTOR; + *total_len += (*total_len - cfg_loop->loop_len) * cfg_loop->loop_cnt; + + dcc_sram_write_auto(drvdata, loop, &cfg->sram_offset); + + cfg_loop->loop_start = false; + cfg_loop->loop_len = 0; + cfg_loop->loop_off = 0; + } else { + cfg_loop->loop_start = true; + cfg_loop->loop_cnt = entry->loop_cnt - 1; + cfg_loop->loop_len = *total_len; + cfg_loop->loop_off = cfg->sram_offset; + } + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); +} + +static void dcc_emit_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + u32 off; + + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->addr = 0x00; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; + } + + off = entry->offset / 4; + /* write new offset-length pair to correct position */ + cfg->link |= ((off & DCC_WRITE_OFF_MASK) | DCC_WRITE_MASK | + FIELD_PREP(DCC_WRITE_LEN_MASK, entry->len)); + cfg->link |= DCC_LINK_DESCRIPTOR; + + /* Address type */ + cfg->addr = (entry->base >> 4) & GENMASK(DCC_ADDR_LIMIT, 0); + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_AHB_IND; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0x00; + cfg->link = 0; +} + +static int dcc_emit_read(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + u32 *pos, u32 *total_len) +{ + u32 off; + u32 temp_off; + + cfg->addr = (entry->base >> 4) & GENMASK(27, 0); + + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_AHB_IND; + + off = entry->offset / 4; + + *total_len += entry->len * 4; + + if (!cfg->prev_addr || cfg->prev_addr != cfg->addr || cfg->prev_off > off) { + /* Check if we need to write prev link entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + dev_dbg(drvdata->dev, "DCC: sram address 0x%x\n", cfg->sram_offset); + + /* Write address */ + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->link = 0; + cfg->prev_off = 0; + } + + if ((off - cfg->prev_off) > 0xff || entry->len > MAX_DCC_LEN) { + dev_err(drvdata->dev, "DCC: Programming error Base: 0x%x, offset 0x%x\n", + entry->base, entry->offset); + return -EINVAL; + } + + if (cfg->link) { + /* + * link already has one offset-length so new + * offset-length needs to be placed at + * bits [29:15] + */ + *pos = 15; + + /* Clear bits [31:16] */ + cfg->link &= GENMASK(14, 0); + } else { + /* + * link is empty, so new offset-length needs + * to be placed at bits [15:0] + */ + *pos = 0; + cfg->link = 1 << 15; + } + + /* write new offset-length pair to correct position */ + temp_off = (off - cfg->prev_off) & GENMASK(7, 0); + cfg->link |= (temp_off | ((entry->len << 8) & GENMASK(14, 8))) << *pos; + + cfg->link |= DCC_LINK_DESCRIPTOR; + + if (*pos) { + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + cfg->link = 0; + } + + cfg->prev_off = off + entry->len - 1; + cfg->prev_addr = cfg->addr; + return 0; +} + +static int dcc_emit_config(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 total_len, pos; + struct dcc_config_entry *entry; + struct dcc_cfg_attr cfg = {0}; + struct dcc_cfg_loop_attr cfg_loop = {0}; + + cfg.sram_offset = drvdata->ram_cfg * 4; + total_len = 0; + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + dcc_emit_read_write(drvdata, entry, &cfg); + break; + + case DCC_LOOP_TYPE: + dcc_emit_loop(drvdata, entry, &cfg, &cfg_loop, &total_len); + break; + + case DCC_WRITE_TYPE: + dcc_emit_write(drvdata, entry, &cfg); + break; + + case DCC_READ_TYPE: + ret = dcc_emit_read(drvdata, entry, &cfg, &pos, &total_len); + if (ret) + goto err; + break; + } + } + + if (cfg.link) + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + if (cfg_loop.loop_start) { + dev_err(drvdata->dev, "DCC: Programming error: Loop unterminated\n"); + ret = -EINVAL; + goto err; + } + + /* Handling special case of list ending with a rd_mod_wr */ + if (cfg.addr == DCC_RD_MOD_WR_DESCRIPTOR) { + cfg.addr = (DCC_RD_MOD_WR_ADDR) & GENMASK(27, 0); + cfg.addr |= DCC_ADDR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.addr, &cfg.sram_offset); + } + + /* Setting zero to indicate end of the list */ + cfg.link = DCC_LINK_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + /* Check if sram offset exceeds the ram size */ + if (cfg.sram_offset > drvdata->ram_size) + goto overstep; + + /* Update ram_cfg and check if the data will overstep */ + drvdata->ram_cfg = (cfg.sram_offset + total_len) / 4; + + if (cfg.sram_offset + total_len > drvdata->ram_size) { + cfg.sram_offset += total_len; + goto overstep; + } + + drvdata->ram_start = cfg.sram_offset / 4; + return 0; +overstep: + ret = -EINVAL; + memset_io(drvdata->ram_base, 0, drvdata->ram_size); + +err: + return ret; +} + +static bool dcc_valid_list(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + u32 lock_reg; + + if (list_empty(&drvdata->cfg_head[curr_list])) + return false; + + if (test_bit(curr_list, drvdata->enable_bitmap)) { + dev_err(drvdata->dev, "List %d is already enabled\n", curr_list); + return false; + } + + lock_reg = dcc_list_readl(drvdata, curr_list, DCC_LL_LOCK); + if (lock_reg & DCC_LOCK_MASK) { + dev_err(drvdata->dev, "List %d is already locked\n", curr_list); + return false; + } + + return true; +} + +static bool is_dcc_enabled(struct dcc_drvdata *drvdata) +{ + int list; + + for (list = 0; list < drvdata->max_link_list; list++) + if (test_bit(list, drvdata->enable_bitmap)) + return true; + + return false; +} + +static int dcc_enable(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 ram_cfg_base; + + mutex_lock(&drvdata->mutex); + + if (!dcc_valid_list(drvdata, curr_list)) { + ret = -EINVAL; + goto out_unlock; + } + + /* Fill dcc sram with the poison value. + * This helps in understanding bus + * hang from registers returning a zero + */ + if (!is_dcc_enabled(drvdata)) + memset_io(drvdata->ram_base, 0xde, drvdata->ram_size); + + /* 1. Take ownership of the list */ + dcc_list_writel(drvdata, DCC_LOCK_MASK, curr_list, DCC_LL_LOCK); + + /* 2. Program linked-list in the SRAM */ + ram_cfg_base = drvdata->ram_cfg; + ret = dcc_emit_config(drvdata, curr_list); + if (ret) { + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + goto out_unlock; + } + + /* 3. Program DCC_RAM_CFG reg */ + dcc_list_writel(drvdata, ram_cfg_base + + drvdata->ram_offset / 4, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, drvdata->ram_start + + drvdata->ram_offset / 4, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0xFFF, curr_list, DCC_LL_TIMEOUT); + + /* 4. Clears interrupt status register */ + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_INT_ENABLE); + dcc_list_writel(drvdata, (BIT(0) | BIT(1) | BIT(2)), + curr_list, DCC_LL_INT_STATUS); + + set_bit(curr_list, drvdata->enable_bitmap); + + /* 5. Configure trigger */ + if (drvdata->mem_map_ver == MEM_MAP_VER3) + dcc_list_writel(drvdata, BIT(8), + curr_list, DCC_LL_CFG); + else + dcc_list_writel(drvdata, DCC_TRIGGER_MASK, + curr_list, DCC_LL_CFG); + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_disable(struct dcc_drvdata *drvdata, int curr_list) +{ + mutex_lock(&drvdata->mutex); + + if (!test_bit(curr_list, drvdata->enable_bitmap)) + goto out_unlock; + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_CFG); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + clear_bit(curr_list, drvdata->enable_bitmap); +out_unlock: + mutex_unlock(&drvdata->mutex); +} + +static u32 dcc_filp_curr_list(const struct file *filp) +{ + struct dentry *dentry = file_dentry(filp); + int curr_list, ret; + + ret = kstrtoint(dentry->d_parent->d_name.name, 0, &curr_list); + if (ret) + return ret; + + return curr_list; +} + +static ssize_t enable_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + int curr_list = dcc_filp_curr_list(filp); + struct dcc_drvdata *drvdata = filp->private_data; + + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + if (test_bit(curr_list, drvdata->enable_bitmap)) + buf = "Y\n"; + else + buf = "N\n"; + mutex_unlock(&drvdata->mutex); + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); +} + +static ssize_t enable_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + int ret = 0, curr_list; + bool val; + struct dcc_drvdata *drvdata = filp->private_data; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) + return curr_list; + + ret = kstrtobool_from_user(userbuf, count, &val); + if (ret < 0) + return ret; + + if (val) { + ret = dcc_enable(drvdata, curr_list); + if (ret) + return ret; + } else { + dcc_disable(drvdata, curr_list); + } + + return count; +} + +static const struct file_operations enable_fops = { + .read = enable_read, + .write = enable_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t trigger_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret; + unsigned int val; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) + return -EINVAL; + + ret = dcc_sw_trigger(drvdata); + if (ret < 0) + return ret; + + return count; +} + +static const struct file_operations trigger_fops = { + .write = trigger_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int len, bool apb_bus, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry, *pentry; + unsigned int base, offset; + + mutex_lock(&drvdata->mutex); + + if (!len || len > drvdata->ram_size / DCC_WORD_SIZE) { + dev_err(drvdata->dev, "DCC: Invalid length\n"); + ret = -EINVAL; + goto out_unlock; + } + + base = addr & DCC_ADDR_RANGE_MASK; + + if (!list_empty(&drvdata->cfg_head[curr_list])) { + pentry = list_last_entry(&drvdata->cfg_head[curr_list], + struct dcc_config_entry, list); + + if (pentry->desc_type == DCC_READ_TYPE && + addr >= (pentry->base + pentry->offset) && + addr <= (pentry->base + pentry->offset + MAX_DCC_OFFSET)) { + /* Re-use base address from last entry */ + base = pentry->base; + + if ((pentry->len * 4 + pentry->base + pentry->offset) + == addr) { + len += pentry->len; + + if (len > MAX_DCC_LEN) + pentry->len = MAX_DCC_LEN; + else + pentry->len = len; + + addr = pentry->base + pentry->offset + + pentry->len * 4; + len -= pentry->len; + } + } + } + + offset = addr - base; + + while (len) { + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->base = base; + entry->offset = offset; + entry->len = min_t(u32, len, MAX_DCC_LEN); + entry->desc_type = DCC_READ_TYPE; + entry->apb_bus = apb_bus; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, + &drvdata->cfg_head[curr_list]); + + len -= entry->len; + offset += MAX_DCC_LEN * 4; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int len, nval; + unsigned int base; + char apb_bus[4]; + + nval = sscanf(buf, "%x %i %3s", &base, &len, apb_bus); + if (nval <= 0 || nval > 3) + return -EINVAL; + + if (nval == 1) { + len = 1; + bus = false; + } else if (nval == 2) { + bus = false; + } else if (!strcmp("apb", apb_bus)) { + bus = true; + } else if (!strcmp("ahb", apb_bus)) { + bus = false; + } else { + return -EINVAL; + } + + return dcc_config_add(drvdata, base, len, bus, curr_list); +} + +static void dcc_config_reset(struct dcc_drvdata *drvdata) +{ + struct dcc_config_entry *entry, *temp; + int curr_list; + + mutex_lock(&drvdata->mutex); + + for (curr_list = 0; curr_list < drvdata->max_link_list; curr_list++) { + list_for_each_entry_safe(entry, temp, + &drvdata->cfg_head[curr_list], list) { + list_del(&entry->list); + } + } + drvdata->ram_start = 0; + drvdata->ram_cfg = 0; + mutex_unlock(&drvdata->mutex); +} + +static ssize_t config_reset_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + unsigned int val; + int ret; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val) + dcc_config_reset(drvdata); + + return count; +} + +static const struct file_operations config_reset_fops = { + .write = config_reset_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t ready_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + struct dcc_drvdata *drvdata = filp->private_data; + + if (!is_dcc_enabled(drvdata)) + return -EINVAL; + + if (!FIELD_GET(BIT(1), readl(drvdata->base + dcc_status(drvdata->mem_map_ver)))) + buf = "Y\n"; + else + buf = "N\n"; + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations ready_fops = { + .read = ready_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t loop_offset_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char buf[4]; + struct dcc_drvdata *drvdata = filp->private_data; + + snprintf(buf, sizeof(buf), "%d", drvdata->loop_shift); + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations loop_offset_fops = { + .read = loop_offset_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; +static int dcc_add_loop(struct dcc_drvdata *drvdata, unsigned long loop_cnt, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->loop_cnt = min_t(u32, loop_cnt, MAX_LOOP_CNT); + entry->desc_type = DCC_LOOP_TYPE; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_loop(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret, i = 0; + char *token, *input; + char delim[2] = " "; + unsigned int val[MAX_LOOP_ADDR]; + + input = buf; + + while ((token = strsep(&input, delim)) && i < MAX_LOOP_ADDR) { + ret = kstrtouint(token, 0, &val[i++]); + if (ret) + return ret; + } + + if (token) { + dev_err(drvdata->dev, "Max limit %u of loop address exceeded\n", + MAX_LOOP_ADDR); + return -EINVAL; + } + + if (val[1] < 1 || val[1] > 8 || val[1] > (i - 2)) + return -EINVAL; + + ret = dcc_add_loop(drvdata, val[0], curr_list); + if (ret) + return ret; + + for (i = 0; i < val[1]; i++) + dcc_config_add(drvdata, val[i + 2], 1, false, curr_list); + + return dcc_add_loop(drvdata, 1, curr_list); +} + +static int dcc_rd_mod_wr_add(struct dcc_drvdata *drvdata, unsigned int mask, + unsigned int val, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry; + + mutex_lock(&drvdata->mutex); + + if (list_empty(&drvdata->cfg_head[curr_list])) { + dev_err(drvdata->dev, "DCC: No read address programmed\n"); + ret = -EPERM; + goto out_unlock; + } + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->desc_type = DCC_READ_WRITE_TYPE; + entry->mask = mask; + entry->write_val = val; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret; + int nval; + unsigned int addr, mask, val; + + nval = sscanf(buf, "%x %x %x", &addr, &mask, &val); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + ret = dcc_config_add(drvdata, addr, 1, false, curr_list); + if (ret) + return ret; + + return dcc_rd_mod_wr_add(drvdata, mask, val, curr_list); +} + +static int dcc_add_write(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int write_val, int apb_bus, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->desc_type = DCC_WRITE_TYPE; + entry->base = addr & GENMASK(31, 4); + entry->offset = addr - entry->base; + entry->write_val = write_val; + entry->len = 1; + entry->apb_bus = apb_bus; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int nval; + unsigned int addr, write_val; + char apb_bus[4]; + + nval = sscanf(buf, "%x %x %3s", &addr, &write_val, apb_bus); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + if (nval == 2) + bus = false; + + if (nval == 3) { + if (!strcmp("apb", apb_bus)) + bus = true; + else if (!strcmp("ahb", apb_bus)) + bus = false; + else + return -EINVAL; + } + + return dcc_add_write(drvdata, addr, write_val, bus, curr_list); +} + +static int config_show(struct seq_file *m, void *data) +{ + struct dcc_drvdata *drvdata = m->private; + struct dcc_config_entry *entry, *next_entry, *prev_entry, *loop_entry; + int index = 0, curr_list, i; + unsigned int loop_val[MAX_LOOP_ADDR]; + + curr_list = dcc_filp_curr_list(m->file); + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + index++; + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + prev_entry = list_prev_entry(entry, list); + seq_printf(m, "RW 0x%x 0x%x 0x%x\n", + prev_entry->base + prev_entry->offset, + entry->mask, + entry->write_val); + break; + case DCC_LOOP_TYPE: + loop_entry = entry; + loop_val[0] = loop_entry->loop_cnt; + loop_entry = list_next_entry(loop_entry, list); + for (i = 0; i < (MAX_LOOP_ADDR-2); + i++, loop_entry = list_next_entry(loop_entry, list)) { + if (loop_entry->desc_type == DCC_READ_TYPE) { + loop_val[i+2] = loop_entry->base + loop_entry->offset; + } else if (loop_entry->desc_type == DCC_LOOP_TYPE) { + loop_val[i+2] = loop_entry->loop_cnt; + loop_val[1] = i; + entry = loop_entry; + break; + } + } + seq_printf(m, "L 0x%x 0x%x", loop_val[0], loop_val[1]); + for (i = 0; i < loop_val[1]; i++) + seq_printf(m, " 0x%x", loop_val[i+2]); + seq_puts(m, "\n"); + break; + case DCC_WRITE_TYPE: + seq_printf(m, "W 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->write_val, + entry->apb_bus ? "apb":"ahb"); + break; + case DCC_READ_TYPE: + if (entry->len == 1) { + next_entry = list_next_entry(entry, list); + if (next_entry && next_entry->desc_type == DCC_READ_WRITE_TYPE) + continue; + } + seq_printf(m, "R 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->len, + entry->apb_bus ? "apb":"ahb"); + } + } + mutex_unlock(&drvdata->mutex); + return 0; +} + +static int config_open(struct inode *inode, struct file *file) +{ + struct dcc_drvdata *drvdata = inode->i_private; + + return single_open(file, config_show, drvdata); +} + +static ssize_t config_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret, curr_list; + char *token, *line; + char *buf, *bufp, *temp_buff; + char *delim = " "; + struct dcc_drvdata *drvdata = filp->f_inode->i_private; + ssize_t processed_len = 0; + + if (count == 0) + return -EINVAL; + buf = kzalloc(count+1, GFP_KERNEL); + if (buf) + bufp = buf; + else + return -ENOMEM; + + ret = copy_from_user(buf, user_buf, count); + if (ret) + goto err; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) { + ret = curr_list; + goto err; + } + + while (bufp[0] != '\0') { + /* Parse line by line */ + line = strsep(&bufp, "\n"); + /* When one complete line could be parsed */ + if (line && bufp) { + processed_len += strlen(line) + 1; + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + temp_buff = drvdata->temp_buff_ptr[curr_list]; + /* Size of combined string must not be greater than + * allowed line size. + */ + if (strlen(line) + strlen(temp_buff) + 1 > LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + strlcat(temp_buff, line, PAGE_SIZE); + line = temp_buff; + kfree(temp_buff); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + + token = strsep(&line, delim); + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, line, curr_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, line, curr_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, line, curr_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, line, curr_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret) + goto err; + } else { + /* Save the incomplete line to a temporary buffer and rejoin it later */ + if (!drvdata->temp_buff_ptr) { + drvdata->temp_buff_ptr = devm_kcalloc(drvdata->dev, + drvdata->max_link_list, + sizeof(char *), + GFP_KERNEL); + if (!drvdata->temp_buff_ptr) { + ret = -ENOMEM; + goto err; + } + } + drvdata->temp_buff_ptr[curr_list] = kzalloc(LINE_BUFFER_MAX_SZ, + GFP_KERNEL); + temp_buff = drvdata->temp_buff_ptr[curr_list]; + if (!temp_buff) { + ret = -ENOMEM; + goto err; + } + if ((count - processed_len) >= LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + memcpy(temp_buff, line, count - processed_len); + temp_buff[count - processed_len + 1] = '\0'; + processed_len += (strlen(temp_buff) + 1); + break; + } + } + + kfree(buf); + return processed_len; + +err: + kfree(buf); + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + kfree(drvdata->temp_buff_ptr[curr_list]); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + return ret; +} + +static const struct file_operations config_fops = { + .open = config_open, + .read = seq_read, + .write = config_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static void dcc_delete_debug_dir(struct dcc_drvdata *drvdata) +{ + debugfs_remove_recursive(drvdata->dbg_dir); +}; + +static void dcc_create_debug_dir(struct dcc_drvdata *drvdata) +{ + int i; + char list_num[10]; + struct dentry *dcc_dev, *list; + struct device *dev = drvdata->dev; + + drvdata->dbg_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + dcc_dev = debugfs_create_dir(dev_name(dev), drvdata->dbg_dir); + + for (i = 0; i < drvdata->max_link_list; i++) { + snprintf(list_num, sizeof(list_num), "%d", i); + list = debugfs_create_dir(list_num, dcc_dev); + debugfs_create_file("enable", 0600, list, drvdata, &enable_fops); + debugfs_create_file("config", 0600, list, drvdata, &config_fops); + } + + debugfs_create_file("trigger", 0200, drvdata->dbg_dir, drvdata, &trigger_fops); + debugfs_create_file("ready", 0400, drvdata->dbg_dir, drvdata, &ready_fops); + debugfs_create_file("config_reset", 0200, drvdata->dbg_dir, drvdata, &config_reset_fops); + debugfs_create_file("loop_offset", 0400, drvdata->dbg_dir, drvdata, &loop_offset_fops); +} + +static ssize_t dcc_sram_read(struct file *file, char __user *data, + size_t len, loff_t *ppos) +{ + unsigned char *buf; + struct dcc_drvdata *drvdata; + + drvdata = container_of(file->private_data, struct dcc_drvdata, + sram_dev); + + /* EOF check */ + if (*ppos >= drvdata->ram_size) + return 0; + + if ((*ppos + len) > drvdata->ram_size) + len = (drvdata->ram_size - *ppos); + + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy_fromio(buf, drvdata->ram_base + *ppos, len); + + if (copy_to_user(data, buf, len)) { + kfree(buf); + return -EFAULT; + } + + *ppos += len; + + kfree(buf); + + return len; +} + +static void dcc_configure_list(struct dcc_drvdata *drvdata, struct device_node *np) +{ + const char *prop; + int ret, curr_list, index = 0; + char *token, *bufp; + char *delim = " "; + u32 len, processed_len = 0; + + ret = of_property_read_u32(np, "qcom,curr-link-list", + &curr_list); + if (ret) + return; + + if(!of_get_property(np, "qcom,link-list", &len)) + return; + + bufp = kzalloc(len+1, GFP_KERNEL); + if (!bufp) + return; + + while (!of_property_read_string_index(np, "qcom,link-list", index, &prop)) { + strncpy(bufp, prop, strlen(prop)); + bufp[strlen(prop)] = '\0'; + + processed_len += strlen(bufp) + 1; + + token = strsep(&bufp, delim); + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, bufp, curr_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, bufp, curr_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, bufp, curr_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, bufp, curr_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret < 0) + dev_err(drvdata->dev, "Configure line %s failed\n", prop); + + index++; + } + + dcc_enable(drvdata, curr_list); + kfree(bufp); +} + +static const struct file_operations dcc_sram_fops = { + .owner = THIS_MODULE, + .read = dcc_sram_read, +}; + +static int dcc_sram_dev_init(struct dcc_drvdata *drvdata) +{ + drvdata->sram_dev.minor = MISC_DYNAMIC_MINOR; + drvdata->sram_dev.name = "dcc_sram"; + drvdata->sram_dev.fops = &dcc_sram_fops; + + return misc_register(&drvdata->sram_dev); +} + +static void dcc_sram_dev_exit(struct dcc_drvdata *drvdata) +{ + misc_deregister(&drvdata->sram_dev); +} + +static int dcc_probe(struct platform_device *pdev) +{ + u32 val; + int ret = 0, i; + struct device *dev = &pdev->dev; + struct dcc_drvdata *drvdata; + struct resource *res; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + drvdata->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + drvdata->ram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); + if (IS_ERR(drvdata->ram_base)) + return PTR_ERR(drvdata->ram_base); + + drvdata->ram_size = resource_size(res); + ret = of_property_read_u32(pdev->dev.of_node, "qcom,dcc-offset", + &drvdata->ram_offset); + if (ret) + return -EINVAL; + + drvdata->mem_map_ver = (u64)of_device_get_match_data(&pdev->dev); + + switch (drvdata->mem_map_ver) { + case MEM_MAP_VER3: + case MEM_MAP_VER2: + drvdata->max_link_list = readl(drvdata->base + DCC_LL_NUM_INFO); + if (!drvdata->max_link_list) + return -EINVAL; + break; + case MEM_MAP_VER1: + drvdata->max_link_list = DCC_MAX_LINK_LIST; + break; + default: + dev_err(drvdata->dev, "Unsupported memory map version.\n"); + return -EINVAL; + } + + val = readl(drvdata->base + DCC_HW_INFO); + /* Either set the fixed loop offset or calculate + * it from the total number of words in dcc_sram. + * Max consecutive addresses dcc can loop is + * equivalent to the words in dcc_sram. + */ + if (val & DCC_LOOP_OFFSET_MASK) + drvdata->loop_shift = DCC_FIX_LOOP_OFFSET; + else + drvdata->loop_shift = get_bitmask_order((drvdata->ram_offset + + drvdata->ram_size) / DCC_SRAM_WORD_LENGTH - 1); + + mutex_init(&drvdata->mutex); + + drvdata->enable_bitmap = devm_kcalloc(dev, BITS_TO_LONGS(drvdata->max_link_list), + sizeof(*drvdata->enable_bitmap), GFP_KERNEL); + if (!drvdata->enable_bitmap) + return -ENOMEM; + + drvdata->cfg_head = devm_kcalloc(dev, drvdata->max_link_list, + sizeof(*drvdata->cfg_head), GFP_KERNEL); + if (!drvdata->cfg_head) + return -ENOMEM; + + for (i = 0; i < drvdata->max_link_list; i++) + INIT_LIST_HEAD(&drvdata->cfg_head[i]); + + ret = dcc_sram_dev_init(drvdata); + if (ret) { + dev_err(drvdata->dev, "DCC: sram node not registered.\n"); + return ret; + } + + dcc_create_debug_dir(drvdata); + dcc_configure_list(drvdata, pdev->dev.of_node); + + return 0; +} + +static void dcc_remove(struct platform_device *pdev) +{ + struct dcc_drvdata *drvdata = platform_get_drvdata(pdev); + + dcc_delete_debug_dir(drvdata); + dcc_sram_dev_exit(drvdata); + dcc_config_reset(drvdata); +} + +static const struct of_device_id dcc_match_table[] = { + { .compatible = "qcom,dcc-v1", .data = (void *)MEM_MAP_VER1 }, + { .compatible = "qcom,dcc-v2", .data = (void *)MEM_MAP_VER2 }, + { .compatible = "qcom,dcc-v3", .data = (void *)MEM_MAP_VER3 }, + { } +}; +MODULE_DEVICE_TABLE(of, dcc_match_table); + +static struct platform_driver dcc_driver = { + .probe = dcc_probe, + .remove = dcc_remove, + .driver = { + .name = "qcom-dcc", + .of_match_table = dcc_match_table, + }, +}; + +module_platform_driver(dcc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver"); From 33b2ed518990c1f6c1c1509567a83901c3d42c07 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 11:28:06 +0800 Subject: [PATCH 0003/1058] QCLINUX: add qcom_debug.config for debug features The config file is created to contain specific debug features such as DCC/memory dump driver. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + 1 file changed, 1 insertion(+) create mode 100644 arch/arm64/configs/qcom_debug.config diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config new file mode 100644 index 0000000000000..874f80f29d314 --- /dev/null +++ b/arch/arm64/configs/qcom_debug.config @@ -0,0 +1 @@ +CONFIG_QCOM_DCC=m From 0fcb861bbaa6bbc39de7c1fbe16335e5c37438f9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 17:47:45 +0800 Subject: [PATCH 0004/1058] QCLINUX: qcom-dcc: add qcom-dcc dev driver Create qcom-dcc dev driver for matching the qcom-dcc driver without DT. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/misc/Kconfig | 8 +- drivers/misc/Makefile | 1 + drivers/misc/qcom-dcc-dev.c | 116 +++++++++++++++++++++++++++ drivers/misc/qcom-dcc.c | 79 ++---------------- drivers/misc/qcom-dcc.h | 20 +++++ 6 files changed, 153 insertions(+), 72 deletions(-) create mode 100644 drivers/misc/qcom-dcc-dev.c create mode 100644 drivers/misc/qcom-dcc.h diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 874f80f29d314..eb2b32af3b40b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1 +1,2 @@ CONFIG_QCOM_DCC=m +CONFIG_QCOM_DCC_DEV=m diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 62b73f320df6d..02388dcebba1f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -310,13 +310,19 @@ config QCOM_FASTRPC module. config QCOM_DCC - tristate "Qualcomm Technologies, Inc. Data Capture and Compare (DCC) engine driver" + tristate "Qualcomm Data Capture and Compare (DCC) engine driver" depends on ARCH_QCOM || COMPILE_TEST help This option enables the driver for the Data Capture and Compare engine. DCC driver provides interfaces to configure DCC block and read back the captured data from the DCC's internal SRAM. The module name for this is qcom-dcc. +config QCOM_DCC_DEV + tristate "Qualcomm Data Capture and Compare (DCC) engine device instance" + depends on QCOM_DCC + help + This is the device instance of the QCOM DCC driver. + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 338ed270b7cfc..812746940d628 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -76,3 +76,4 @@ obj-y += keba/ obj-y += amd-sbi/ obj-$(CONFIG_MISC_RP1) += rp1/ obj-$(CONFIG_QCOM_DCC) += qcom-dcc.o +obj-$(CONFIG_QCOM_DCC_DEV) += qcom-dcc-dev.o diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c new file mode 100644 index 0000000000000..e0eb2e61d652b --- /dev/null +++ b/drivers/misc/qcom-dcc-dev.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include "qcom-dcc.h" + +#define DEV_NAME "qcom-dcc" + +static struct platform_device *dcc_pdev; + +static const struct dcc_pdata talos_pdata = { + .base = 0x010a2000, + .size = 0x00001000, + .ram_base = 0x010ae000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x1, +}; + +static const struct dcc_pdata lemans_pdata = { + .base = 0x040ff000, + .size = 0x00001000, + .ram_base = 0x040b8800, + .ram_size = 0x00006000, + .dcc_offset = 0x38800, + .map_ver = 0x3, +}; + +static const struct dcc_pdata kodiak_pdata = { + .base = 0x0117f000, + .size = 0x00001000, + .ram_base = 0x01112000, + .ram_size = 0x00006000, + .dcc_offset = 0x12000, + .map_ver = 0x2, +}; + +static int __init dcc_dev_init(void) +{ + int ret; + u32 soc_id; + + dcc_pdev = platform_device_alloc(DEV_NAME, -1); + if (!dcc_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(dcc_pdev, &kodiak_pdata, sizeof(kodiak_pdata)); + if (ret) + goto fail; + + break; + case 534: + case 606: + case 667: + case 674: + case 675: + case 676: + ret = platform_device_add_data(dcc_pdev, &lemans_pdata, sizeof(lemans_pdata)); + if (ret) + goto fail; + + break; + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(dcc_pdev, &talos_pdata, sizeof(talos_pdata)); + if (ret) + goto fail; + + break; + default: + pr_err("DCC: Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(dcc_pdev); + if (ret) + goto fail; + + pr_info("DCC platform device has registered\n"); + + return 0; + +fail: + pr_err("Failed to register DCC platform device\n"); + platform_device_put(dcc_pdev); + + return ret; +} + +static void __exit dcc_dev_exit(void) +{ + platform_device_unregister(dcc_pdev); +} + +module_init(dcc_dev_init); +module_exit(dcc_dev_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver, device stub"); diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c index a511faac5d4b0..e75f98b90d8f7 100644 --- a/drivers/misc/qcom-dcc.c +++ b/drivers/misc/qcom-dcc.c @@ -135,6 +135,8 @@ #include #include +#include "qcom-dcc.h" + #define STATUS_READY_TIMEOUT 5000 /* microseconds */ /* DCC registers */ @@ -1423,57 +1425,6 @@ static ssize_t dcc_sram_read(struct file *file, char __user *data, return len; } -static void dcc_configure_list(struct dcc_drvdata *drvdata, struct device_node *np) -{ - const char *prop; - int ret, curr_list, index = 0; - char *token, *bufp; - char *delim = " "; - u32 len, processed_len = 0; - - ret = of_property_read_u32(np, "qcom,curr-link-list", - &curr_list); - if (ret) - return; - - if(!of_get_property(np, "qcom,link-list", &len)) - return; - - bufp = kzalloc(len+1, GFP_KERNEL); - if (!bufp) - return; - - while (!of_property_read_string_index(np, "qcom,link-list", index, &prop)) { - strncpy(bufp, prop, strlen(prop)); - bufp[strlen(prop)] = '\0'; - - processed_len += strlen(bufp) + 1; - - token = strsep(&bufp, delim); - - if (!strcmp("R", token)) { - ret = dcc_config_add_read(drvdata, bufp, curr_list); - } else if (!strcmp("W", token)) { - ret = dcc_config_add_write(drvdata, bufp, curr_list); - } else if (!strcmp("RW", token)) { - ret = dcc_config_add_read_write(drvdata, bufp, curr_list); - } else if (!strcmp("L", token)) { - ret = dcc_config_add_loop(drvdata, bufp, curr_list); - } else { - dev_err(drvdata->dev, "%s is not a correct input\n", token); - ret = -EINVAL; - } - - if (ret < 0) - dev_err(drvdata->dev, "Configure line %s failed\n", prop); - - index++; - } - - dcc_enable(drvdata, curr_list); - kfree(bufp); -} - static const struct file_operations dcc_sram_fops = { .owner = THIS_MODULE, .read = dcc_sram_read, @@ -1499,7 +1450,7 @@ static int dcc_probe(struct platform_device *pdev) int ret = 0, i; struct device *dev = &pdev->dev; struct dcc_drvdata *drvdata; - struct resource *res; + const struct dcc_pdata *pdata = dev_get_platdata(dev); drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) @@ -1508,21 +1459,17 @@ static int dcc_probe(struct platform_device *pdev) drvdata->dev = &pdev->dev; platform_set_drvdata(pdev, drvdata); - drvdata->base = devm_platform_ioremap_resource(pdev, 0); + drvdata->base = devm_ioremap(dev, pdata->base, pdata->size); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata->ram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); + drvdata->ram_base = devm_ioremap(dev, pdata->ram_base, pdata->ram_size); if (IS_ERR(drvdata->ram_base)) return PTR_ERR(drvdata->ram_base); - drvdata->ram_size = resource_size(res); - ret = of_property_read_u32(pdev->dev.of_node, "qcom,dcc-offset", - &drvdata->ram_offset); - if (ret) - return -EINVAL; - - drvdata->mem_map_ver = (u64)of_device_get_match_data(&pdev->dev); + drvdata->ram_size = pdata->ram_size; + drvdata->ram_offset = pdata->dcc_offset; + drvdata->mem_map_ver = pdata->map_ver; switch (drvdata->mem_map_ver) { case MEM_MAP_VER3: @@ -1573,7 +1520,6 @@ static int dcc_probe(struct platform_device *pdev) } dcc_create_debug_dir(drvdata); - dcc_configure_list(drvdata, pdev->dev.of_node); return 0; } @@ -1587,20 +1533,11 @@ static void dcc_remove(struct platform_device *pdev) dcc_config_reset(drvdata); } -static const struct of_device_id dcc_match_table[] = { - { .compatible = "qcom,dcc-v1", .data = (void *)MEM_MAP_VER1 }, - { .compatible = "qcom,dcc-v2", .data = (void *)MEM_MAP_VER2 }, - { .compatible = "qcom,dcc-v3", .data = (void *)MEM_MAP_VER3 }, - { } -}; -MODULE_DEVICE_TABLE(of, dcc_match_table); - static struct platform_driver dcc_driver = { .probe = dcc_probe, .remove = dcc_remove, .driver = { .name = "qcom-dcc", - .of_match_table = dcc_match_table, }, }; diff --git a/drivers/misc/qcom-dcc.h b/drivers/misc/qcom-dcc.h new file mode 100644 index 0000000000000..513c95dc742b5 --- /dev/null +++ b/drivers/misc/qcom-dcc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_H +#define _QCOM_DCC_H + +#include + +struct dcc_pdata { + phys_addr_t base; + resource_size_t size; + phys_addr_t ram_base; + resource_size_t ram_size; + u32 dcc_offset; + u8 map_ver; +}; + +#endif From 01d59d21a9179472325e34a0a1555159f5bd85dd Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 9 Jan 2026 14:42:21 +0800 Subject: [PATCH 0005/1058] QCLINUX: memory-dump: add QCOM memory dump driver The memory dump driver allows various client subsystems to register respective dump regions. At the time of deadlocks or cpu hangs these dump regions are captured to give a snapshot of the system at the time of the crash. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/firmware/qcom/Kconfig | 9 + drivers/firmware/qcom/Makefile | 1 + drivers/firmware/qcom/memory_dump_v2.c | 1143 +++++++++++++++++++++ include/linux/firmware/qcom/memory_dump.h | 136 +++ 5 files changed, 1290 insertions(+) create mode 100644 drivers/firmware/qcom/memory_dump_v2.c create mode 100644 include/linux/firmware/qcom/memory_dump.h diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index eb2b32af3b40b..2e85e8df0469b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,2 +1,3 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m +CONFIG_QCOM_MEMORY_DUMP_V2=m diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index b477d54b495a6..531c6d2598ce0 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -74,4 +74,13 @@ config QCOM_QSEECOM_UEFISECAPP Select Y here to provide access to EFI variables on the aforementioned platforms. +config QCOM_MEMORY_DUMP_V2 + tristate "QCOM Memory Dump V2 Support" + depends on QCOM_TZMEM + help + This enables memory dump feature. It allows various client + subsystems to register respective dump regions. At the time + of deadlocks or cpu hangs these dump regions are captured to + give a snapshot of the system at the time of the crash. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index 0be40a1abc13c..c5e17ba255937 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -8,3 +8,4 @@ qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c new file mode 100644 index 0000000000000..baf4c980f39fb --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -0,0 +1,1143 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) + +#define SCM_CMD_DEBUG_LAR_UNLOCK 0x4 + +#define CPUSS_REGDUMP 0xEF +#define SPR_DUMP_CPU0 0x1F0 +#define SPR_DUMP_CPU1 0x1F1 +#define SPR_DUMP_CPU2 0x1F2 +#define SPR_DUMP_CPU3 0x1F3 +#define SPR_DUMP_CPU4 0x1F4 +#define SPR_DUMP_CPU5 0x1F5 +#define SPR_DUMP_CPU6 0x1F6 +#define SPR_DUMP_CPU7 0x1F7 +#define SPR_DATA_HEADER_SIZE 5 +#define SPR_DATA_HEADER_TAIL_SIZE 1 +#define SPR_INPUT_DATA_TAIL_SIZE 1 +#define SPR_INPUT_DATA_SIZE 1 +#define SPR_OUTPUT_DATA_SIZE 2 +#define MAX_CORE_NUM 8 + +#define INPUT_DATA_BY_HLOS 0x00C0FFEE +#define FORMAT_VERSION_1 0x1 +#define FORMAT_VERSION_2 0x2 +#define CORE_REG_NUM_DEFAULT 0x1 + +#define MAGIC_INDEX 0 +#define FORMAT_VERSION_INDEX 1 +#define SYS_REG_INPUT_INDEX 2 +#define OUTPUT_DUMP_INDEX 3 +#define PERCORE_INDEX 4 +#define SYSTEM_REGS_INPUT_INDEX 5 + +#define CMD_REPEAT_READ (0x2 << 24) +#define CMD_DELAY (0x1 << 24) +#define CMD_READ 0x0 +#define CMD_READ_WORD 0x1 +#define CMD_WRITE 0x2 +#define CMD_EXTRA 0x3 + +#define CMD_MASK 0x3 +#define OFFSET_MASK GENMASK(31, 2) +#define EXTRA_CMD_MASK GENMASK(31, 24) +#define EXTRA_VALUE_MASK GENMASK(23, 0) +#define MAX_EXTRA_VALUE 0xffffff + +struct sprs_dump_data { + void *dump_vaddr; + u32 size; + u32 sprs_data_index; + u32 used_memory; +}; + +struct cpuss_regdump_data { + void *dump_vaddr; + u32 size; + u32 core_reg_num; + u32 core_reg_used_num; + u32 core_reg_end_index; + u32 sys_reg_size; + u32 used_memory; +}; + +struct cpuss_dump_data { + struct mutex mutex; + struct cpuss_regdump_data *cpussregdata; + struct sprs_dump_data *sprdata[MAX_CORE_NUM]; +}; + +struct reg_dump_data { + uint32_t magic; + uint32_t version; + uint32_t system_regs_input_index; + uint32_t regdump_output_byte_offset; +}; + +struct msm_dump_table { + uint32_t version; + uint32_t num_entries; + struct msm_dump_entry entries[MAX_NUM_ENTRIES]; +}; + +struct msm_memory_dump { + uint64_t table_phys; + struct msm_dump_table *table; +}; + +/** + * Set bit 0 if percore reg dump initialized. + * Set bit 1 if spr dump initialized. + */ +#define PERCORE_REG_INITIALIZED BIT(0) +#define SPRS_INITIALIZED BIT(1) + +static struct msm_memory_dump memdump; + +/** + * reset_sprs_dump_table - reset the sprs dump table + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int reset_sprs_dump_table(struct device *dev) +{ + int ret = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + cpudata->sprdata[i]->sprs_data_index = 0; + cpudata->sprdata[i]->used_memory = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset(cpudata->sprdata[i]->dump_vaddr, 0xDE, + cpudata->sprdata[i]->size); + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_1; + p->system_regs_input_index = SYSTEM_REGS_INPUT_INDEX; + p->regdump_output_byte_offset = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset((uint32_t *)cpudata->sprdata[i]->dump_vaddr + + PERCORE_INDEX, 0x0, (SPR_DATA_HEADER_TAIL_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t)); + } + } + + mutex_unlock(&cpudata->mutex); + return ret; +} + + +/** + * update_reg_dump_table - update the register dump table + * @core_reg_num: the number of per-core registers + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int update_reg_dump_table(struct device *dev, u32 core_reg_num) +{ + int ret = 0; + u32 system_regs_input_index = SYSTEM_REGS_INPUT_INDEX + + core_reg_num * 2; + u32 regdump_output_byte_offset = (system_regs_input_index + 1) + * sizeof(uint32_t); + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + mutex_lock(&cpudata->mutex); + + if (regdump_output_byte_offset >= cpudata->cpussregdata->size || + regdump_output_byte_offset / sizeof(uint32_t) + < system_regs_input_index + 1) { + ret = -ENOMEM; + goto err; + } + + cpudata->cpussregdata->core_reg_num = core_reg_num; + cpudata->cpussregdata->core_reg_used_num = 0; + cpudata->cpussregdata->core_reg_end_index = PERCORE_INDEX; + cpudata->cpussregdata->sys_reg_size = 0; + cpudata->cpussregdata->used_memory = regdump_output_byte_offset; + + memset(cpudata->cpussregdata->dump_vaddr, 0xDE, cpudata->cpussregdata->size); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_2; + p->system_regs_input_index = system_regs_input_index; + p->regdump_output_byte_offset = regdump_output_byte_offset; + memset((uint32_t *)cpudata->cpussregdata->dump_vaddr + PERCORE_INDEX, 0x0, + (system_regs_input_index - PERCORE_INDEX + 1) + * sizeof(uint32_t)); + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + ret = scnprintf(buf, PAGE_SIZE, "%u\n", cpudata->cpussregdata->core_reg_num); + + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned int val; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + + mutex_lock(&cpudata->mutex); + + if (cpudata->cpussregdata->core_reg_used_num || cpudata->cpussregdata->sys_reg_size) { + dev_err(dev, "Couldn't set core_reg_num, register available in list\n"); + ret = -EPERM; + goto err; + } + if (val == cpudata->cpussregdata->core_reg_num) { + mutex_unlock(&cpudata->mutex); + return size; + } + + mutex_unlock(&cpudata->mutex); + + ret = update_reg_dump_table(dev, val); + if (ret) { + dev_err(dev, "Couldn't set core_reg_num, no enough memory\n"); + return ret; + } + + return size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(core_reg_num); + +/** + * This function shows configs of per-core and system registers. + */ +static ssize_t register_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + int index, system_index_start, index_end; + uint32_t register_offset, val; + uint32_t *p, cmd; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + + /* print per-core & system registers */ + len = scnprintf(local_buf, 64, "per-core registers:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + system_index_start = *(p + SYS_REG_INPUT_INDEX); + index_end = system_index_start + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t) + 1; + for (index = PERCORE_INDEX; index < index_end;) { + if (index == system_index_start) { + len = scnprintf(local_buf, 64, "system registers:\n"); + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + register_offset = *(p + index); + if (register_offset == 0) { + index++; + continue; + } + + cmd = register_offset & CMD_MASK; + register_offset &= OFFSET_MASK; + + switch (cmd) { + case CMD_READ: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, val); + index += 2; + break; + case CMD_READ_WORD: + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, 0x4); + index++; + break; + case CMD_WRITE: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, w\n", + register_offset, val); + index += 2; + break; + case CMD_EXTRA: + val = *(p + index + 1); + cmd = val & EXTRA_CMD_MASK; + val &= EXTRA_VALUE_MASK; + if (cmd == CMD_DELAY) + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, d\n", + register_offset, val); + else + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, R\n", + register_offset, val); + index += 2; + break; + } + + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +static int config_cpuss_register(struct device *dev, + uint32_t *p, uint32_t index, char cmd, + uint32_t register_offset, uint32_t val) +{ + int ret = 0; + + switch (cmd) { + case 'r': + if (val > 4) { + *(p + index) = register_offset; + *(p + index + 1) = val; + } else { + *(p + index) = register_offset | CMD_READ_WORD; + } + break; + case 'R': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "repeat read time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = register_offset | CMD_EXTRA; + *(p + index + 1) = val | CMD_REPEAT_READ; + break; + case 'd': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "sleep time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = CMD_EXTRA; + *(p + index + 1) = val | CMD_DELAY; + break; + case 'w': + *(p + index) = register_offset | CMD_WRITE; + *(p + index + 1) = val; + break; + default: + dev_err(dev, "Don't support this command\n"); + ret = -EINVAL; + } + return ret; +} +/** + * This function sets configs of per-core or system registers. + */ +static ssize_t register_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + uint32_t register_offset, val, reserve_size = 4, per_core = 0; + int nval; + char cmd; + uint32_t num_cores; + u32 extra_memory; + u32 used_memory; + u32 system_reg_end_index; + uint32_t *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%x %x %c %u", ®ister_offset, + &val, &cmd, &per_core); + if (nval < 2) + return -EINVAL; + if (nval == 2) + cmd = 'r'; + if (per_core > 1) + return -EINVAL; + if (register_offset & 0x3) { + dev_err(dev, "Invalid address, must be 4 byte aligned\n"); + return -EINVAL; + } + + if (cmd == 'r' || cmd == 'R') { + if (val == 0) { + dev_err(dev, "Invalid length of 0\n"); + return -EINVAL; + } + if (cmd == 'r' && val & 0x3) { + dev_err(dev, "Invalid length, must be 4 byte aligned\n"); + return -EINVAL; + } + if (cmd == 'R') + reserve_size = val * 4; + else + reserve_size = val; + } + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + if (per_core) { /* per-core register */ + if (cpudata->cpussregdata->core_reg_used_num == + cpudata->cpussregdata->core_reg_num) { + dev_err(dev, "Couldn't add per-core config, out of range\n"); + ret = -EINVAL; + goto err; + } + + num_cores = num_possible_cpus(); + extra_memory = reserve_size * num_cores; + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory / num_cores < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add per-core reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, cpudata->cpussregdata->core_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) + cpudata->cpussregdata->core_reg_end_index++; + else + cpudata->cpussregdata->core_reg_end_index += 2; + + cpudata->cpussregdata->core_reg_used_num++; + cpudata->cpussregdata->used_memory = used_memory; + } else { /* system register */ + system_reg_end_index = *(p + SYS_REG_INPUT_INDEX) + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t); + + if (cmd == 'r' && reserve_size == 4) + extra_memory = sizeof(uint32_t) + reserve_size; + else + extra_memory = sizeof(uint32_t) * 2 + reserve_size; + + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add system reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, system_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) { + system_reg_end_index++; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t); + } else { + system_reg_end_index += 2; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t) * 2; + } + + cpudata->cpussregdata->used_memory = used_memory; + *(p + system_reg_end_index) = 0x0; + *(p + OUTPUT_DUMP_INDEX) = (system_reg_end_index + 1) + * sizeof(uint32_t); + } + + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(register_config); + +static ssize_t format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + ret = scnprintf(buf, PAGE_SIZE, "%u\n", p->version); + + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RO(format_version); +/** + * This function resets the register dump table. + */ +static ssize_t register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + update_reg_dump_table(dev, CORE_REG_NUM_DEFAULT); + + return size; +} +static DEVICE_ATTR_WO(register_reset); + +/** + * This function shows configs of per-core spr dump. + */ +static ssize_t spr_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0, index = 0; + uint32_t *p; + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + len = scnprintf(local_buf, 64, "spr data list below:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + if (!cpudata->sprdata[i]) { + dev_err(dev, "SPR data pinter for CPU%d is empty\n", i); + continue; + } + p = (uint32_t *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, "spr data for CPU[%d] below:\n", i); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index = 0; + while (index < cpudata->sprdata[i]->sprs_data_index) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + len = scnprintf(local_buf, 64, "%d\n", *(p + SPR_DATA_HEADER_SIZE + index)); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index++; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +/** + * This function sets configs for sprs dump. + */ +static ssize_t spr_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + uint32_t spr_data, cpu_num; + uint32_t index; + int nval; + uint32_t *p; + u32 reserved = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%d %d", &spr_data, &cpu_num); + if (nval != 2) + return -EINVAL; + if (!cpudata) + return -EFAULT; + + if (cpu_num >= MAX_CORE_NUM) { + dev_err(dev, "Input the wrong CPU number\n"); + return -EINVAL; + } + reserved = (SPR_INPUT_DATA_SIZE + SPR_OUTPUT_DATA_SIZE) * sizeof(uint32_t); + + mutex_lock(&cpudata->mutex); + if (cpudata->sprdata[cpu_num]) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + index = cpudata->sprdata[cpu_num]->sprs_data_index; + + if (cpudata->sprdata[cpu_num]->size > + cpudata->sprdata[cpu_num]->used_memory + reserved) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + *(p + OUTPUT_DUMP_INDEX) = (SPR_DATA_HEADER_SIZE + + index + SPR_INPUT_DATA_TAIL_SIZE + 1) * sizeof(uint32_t); + *(p + SPR_DATA_HEADER_SIZE + index) = spr_data; + *(p + SPR_DATA_HEADER_SIZE + index + 1) = 0; + cpudata->sprdata[cpu_num]->sprs_data_index++; + cpudata->sprdata[cpu_num]->used_memory = + cpudata->sprdata[cpu_num]->used_memory + reserved; + } else { + dev_err(dev, "Couldn't add SPR config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + } + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(spr_config); + +/** + * This function resets the sprs dump table. + */ +static ssize_t sprs_register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + reset_sprs_dump_table(dev); + + return size; +} +static DEVICE_ATTR_WO(sprs_register_reset); + +static ssize_t sprs_format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0, i = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, + "SPR data format version for cpu%d is %d\n", i, p->version); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} +static DEVICE_ATTR_RO(sprs_format_version); + + +static const struct device_attribute *register_dump_attrs[] = { + &dev_attr_core_reg_num, + &dev_attr_register_config, + &dev_attr_register_reset, + &dev_attr_format_version, + NULL, +}; + +static const struct device_attribute *spr_dump_attrs[] = { + &dev_attr_spr_config, + &dev_attr_sprs_register_reset, + &dev_attr_sprs_format_version, + NULL, +}; + +static int memory_dump_create_files(struct device *dev, + const struct device_attribute **attrs) +{ + int ret = 0; + int i, j; + + for (i = 0; attrs[i] != NULL; i++) { + ret = device_create_file(dev, attrs[i]); + if (ret) { + dev_err(dev, "Couldn't create sysfs attribute: %s\n", + attrs[i]->attr.name); + for (j = 0; j < i; j++) + device_remove_file(dev, attrs[j]); + break; + } + } + return ret; +} + +static void cpuss_create_nodes(struct platform_device *pdev, + int initialized) +{ + if (initialized & PERCORE_REG_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, register_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for cpuss register dump\n"); + } + if (initialized & SPRS_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, spr_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for spr dump\n"); + } +} + +uint32_t msm_dump_table_version(void) +{ + return MSM_DUMP_TABLE_VERSION; +} +EXPORT_SYMBOL_GPL(msm_dump_table_version); + +static int msm_dump_table_register(struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table = memdump.table; + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_TABLE; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +static struct msm_dump_table *msm_dump_get_table(enum msm_dump_table_ids id) +{ + struct msm_dump_table *table = memdump.table; + int i; + unsigned long offset; + + if (!table) { + pr_err("mem dump base table does not exist\n"); + return ERR_PTR(-EINVAL); + } + + for (i = 0; i < MAX_NUM_ENTRIES; i++) { + if (table->entries[i].id == id) + break; + } + if (i == MAX_NUM_ENTRIES || !table->entries[i].addr) { + pr_err("mem dump base table entry %d invalid\n", id); + return ERR_PTR(-EINVAL); + } + + offset = table->entries[i].addr - memdump.table_phys; + /* Get the apps table pointer */ + table = (void *)memdump.table + offset; + + return table; +} + +static int register_dump_table_entry(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table; + + table = msm_dump_get_table(id); + if (IS_ERR(table)) + return PTR_ERR(table); + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_DATA; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +/** + * msm_dump_data_register_nominidump - register to dump data framework + * @id: ID of the dump table. + * @entry: dump entry to be registered + * This api will register the entry passed to dump table only + */ +int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return register_dump_table_entry(id, entry); +} +EXPORT_SYMBOL_GPL(msm_dump_data_register_nominidump); + +#define MSM_DUMP_TOTAL_SIZE_OFFSET 0x724 +static int init_memdump_imem_area(size_t size) +{ + struct device_node *np; + void __iomem *imem_base; + + np = of_find_compatible_node(NULL, NULL, + "qcom,msm-imem-mem-dump-table"); + if (!np) { + pr_err("mem dump base table DT node does not exist\n"); + return -ENODEV; + } + + imem_base = of_iomap(np, 0); + if (!imem_base) { + pr_err("mem dump base table imem offset mapping failed\n"); + return -ENOMEM; + } + + memcpy_toio(imem_base, &memdump.table_phys, + sizeof(memdump.table_phys)); + memcpy_toio(imem_base + MSM_DUMP_TOTAL_SIZE_OFFSET, + &size, sizeof(size_t)); + + /* Ensure write to imem_base is complete before unmapping */ + mb(); + pr_info("MSM Memory Dump base table set up in IMEM\n"); + + iounmap(imem_base); + return 0; +} + +static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) +{ + struct msm_dump_table *table; + struct msm_dump_entry entry; + int ret; + + memdump.table = dump_vaddr; + memdump.table->version = MSM_DUMP_TABLE_VERSION; + memdump.table_phys = phys_addr; + dump_vaddr += sizeof(*table); + phys_addr += sizeof(*table); + table = dump_vaddr; + table->version = MSM_DUMP_TABLE_VERSION; + entry.id = MSM_DUMP_TABLE_APPS; + entry.addr = phys_addr; + ret = msm_dump_table_register(&entry); + if (ret) { + pr_err("mem dump apps data table register failed\n"); + return ret; + } + pr_info("MSM Memory Dump apps data table set up\n"); + + return 0; +} + +static int mem_dump_reserve_mem(struct device *dev) +{ + struct device_node *mem_node; + int ret; + + mem_node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (mem_node) { + ret = of_reserved_mem_device_init_by_idx(dev, + dev->of_node, 0); + of_node_put(dev->of_node); + if (ret) { + dev_err(dev, + "Failed to initialize reserved mem, ret %d\n", + ret); + return ret; + } + } + return 0; +} + +static int cpuss_regdump_init(struct device *dev, + void *dump_vaddr, u32 size) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + cpudata->cpussregdata = devm_kzalloc(dev, + sizeof(struct cpuss_regdump_data), GFP_KERNEL); + + if (cpudata->cpussregdata) { + cpudata->cpussregdata->dump_vaddr = dump_vaddr; + cpudata->cpussregdata->size = size; + return 0; + } + return -ENOMEM; +} + +static int sprs_dump_init(struct device *dev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int core_num = 0; + + core_num = id - SPR_DUMP_CPU0; + + cpudata->sprdata[core_num] = devm_kzalloc(dev, + sizeof(struct sprs_dump_data), GFP_KERNEL); + if (cpudata->sprdata[core_num]) { + cpudata->sprdata[core_num]->dump_vaddr = dump_vaddr; + cpudata->sprdata[core_num]->size = size; + return 0; + } + return -ENOMEM; +} + +static int cpuss_dump_init(struct platform_device *pdev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(&pdev->dev); + static int initialized; + + if (!cpudata) { + cpudata = devm_kzalloc(&pdev->dev, + sizeof(struct cpuss_dump_data), GFP_KERNEL); + if (cpudata) { + mutex_init(&cpudata->mutex); + platform_set_drvdata(pdev, cpudata); + } else + return initialized; + } + + if (id == CPUSS_REGDUMP) { + if (!cpuss_regdump_init(&pdev->dev, dump_vaddr, size)) + initialized |= PERCORE_REG_INITIALIZED; + } else { + if (!sprs_dump_init(&pdev->dev, dump_vaddr, size, id)) + initialized |= SPRS_INITIALIZED; + } + + return initialized; +} + +#define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) +static int mem_dump_alloc(struct platform_device *pdev) +{ + struct device_node *child_node; + const struct device_node *node = pdev->dev.of_node; + struct msm_dump_data *dump_data; + struct msm_dump_entry dump_entry; + size_t total_size; + u32 size, id; + int ret, no_of_nodes; + dma_addr_t dma_handle; + phys_addr_t phys_addr; + struct sg_table mem_dump_sgt; + void *dump_vaddr; + u64 shm_bridge_handle; + int initialized = 0; + + if (mem_dump_reserve_mem(&pdev->dev) != 0) + return -ENOMEM; + total_size = size = ret = no_of_nodes = 0; + /* For dump table registration with IMEM */ + total_size = sizeof(struct msm_dump_table) * 2; + for_each_available_child_of_node(node, child_node) { + ret = of_property_read_u32(child_node, "qcom,dump-size", &size); + if (ret) { + dev_err(&pdev->dev, "Unable to find size for %s\n", + child_node->name); + continue; + } + + total_size += size; + no_of_nodes++; + } + + total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); + total_size = ALIGN(total_size, SZ_4K); + dump_vaddr = dmam_alloc_coherent(&pdev->dev, total_size, + &dma_handle, GFP_KERNEL); + if (!dump_vaddr) + return -ENOMEM; + + dma_get_sgtable(&pdev->dev, &mem_dump_sgt, dump_vaddr, + dma_handle, total_size); + phys_addr = page_to_phys(sg_page(mem_dump_sgt.sgl)); + sg_free_table(&mem_dump_sgt); + + memset(dump_vaddr, 0x0, total_size); + ret = qcom_tzmem_shm_bridge_create(phys_addr, total_size, &shm_bridge_handle); + if (ret) { + dev_err(&pdev->dev, "Failed to create shm bridge.ret=%d\n", ret); + return ret; + } + + ret = init_memory_dump(dump_vaddr, phys_addr); + if (ret) { + dev_err(&pdev->dev, "Memory Dump table set up is failed\n"); + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + ret = init_memdump_imem_area(total_size); + if (ret) { + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + dump_vaddr += (sizeof(struct msm_dump_table) * 2); + phys_addr += (sizeof(struct msm_dump_table) * 2); + for_each_available_child_of_node(node, child_node) { + ret = of_property_read_u32(child_node, "qcom,dump-size", &size); + if (ret) + continue; + + ret = of_property_read_u32(child_node, "qcom,dump-id", &id); + if (ret) { + dev_err(&pdev->dev, "Unable to find id for %s\n", + child_node->name); + continue; + } + + dump_data = dump_vaddr; + dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; + dump_data->len = size; + dump_entry.id = id; + strscpy(dump_data->name, child_node->name, + sizeof(dump_data->name)); + dump_entry.addr = phys_addr; + ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, + &dump_entry); + if (ret) + dev_err(&pdev->dev, "Data dump setup failed, id = %d\n", + id); + + if ((id == CPUSS_REGDUMP) || + ((id >= SPR_DUMP_CPU0) && (id <= SPR_DUMP_CPU7))) + initialized = cpuss_dump_init(pdev, + (dump_vaddr + MSM_DUMP_DATA_SIZE), size, id); + + dump_vaddr += (size + MSM_DUMP_DATA_SIZE); + phys_addr += (size + MSM_DUMP_DATA_SIZE); + } + + cpuss_create_nodes(pdev, initialized); + + if (initialized & SPRS_INITIALIZED) + reset_sprs_dump_table(&pdev->dev); + + return ret; +} + +static int mem_dump_probe(struct platform_device *pdev) +{ + int ret; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret < 0) + return ret; + + ret = mem_dump_alloc(pdev); + return ret; +} + +static const struct of_device_id mem_dump_match_table[] = { + {.compatible = "qcom,mem-dump",}, + {} +}; + +static struct platform_driver mem_dump_driver = { + .probe = mem_dump_probe, + .driver = { + .name = "msm_mem_dump", + .of_match_table = mem_dump_match_table, + }, +}; + +module_platform_driver(mem_dump_driver); + +MODULE_DESCRIPTION("Memory Dump V2 Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h new file mode 100644 index 0000000000000..ebb7c89d2f243 --- /dev/null +++ b/include/linux/firmware/qcom/memory_dump.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012, 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_MEMORY_DUMP_H +#define __MSM_MEMORY_DUMP_H + +#include +#include + +enum dump_client_type { + MSM_CPU_CTXT = 0, + MSM_L1_CACHE, + MSM_L2_CACHE, + MSM_OCMEM, + MSM_TMC_ETFETB, + MSM_ETM0_REG, + MSM_ETM1_REG, + MSM_ETM2_REG, + MSM_ETM3_REG, + MSM_TMC0_REG, /* TMC_ETR */ + MSM_TMC1_REG, /* TMC_ETF */ + MSM_LOG_BUF, + MSM_LOG_BUF_FIRST_IDX, + MAX_NUM_CLIENTS, +}; + +struct msm_client_dump { + enum dump_client_type id; + unsigned long start_addr; + unsigned long end_addr; +}; + +#ifdef CONFIG_QCOM_MEMORY_DUMP +extern int msm_dump_tbl_register(struct msm_client_dump *client_entry); +#else +static inline int msm_dump_tbl_register(struct msm_client_dump *entry) +{ + return -EIO; +} +#endif + + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern uint32_t msm_dump_table_version(void); +#else +static inline uint32_t msm_dump_table_version(void) +{ + return 0; +} +#endif + +#define MSM_DUMP_MAKE_VERSION(ma, mi) ((ma << 20) | mi) +#define MSM_DUMP_MAJOR(val) (val >> 20) +#define MSM_DUMP_MINOR(val) (val & 0xFFFFF) + + +#define MAX_NUM_ENTRIES 0x150 + +enum msm_dump_data_ids { + MSM_DUMP_DATA_CPU_CTX = 0x00, + MSM_DUMP_DATA_L1_INST_CACHE = 0x60, + MSM_DUMP_DATA_L1_DATA_CACHE = 0x80, + MSM_DUMP_DATA_ETM_REG = 0xA0, + MSM_DUMP_DATA_L2_CACHE = 0xC0, + MSM_DUMP_DATA_L3_CACHE = 0xD0, + MSM_DUMP_DATA_OCMEM = 0xE0, + MSM_DUMP_DATA_CNSS_WLAN = 0xE1, + MSM_DUMP_DATA_WIGIG = 0xE2, + MSM_DUMP_DATA_PMIC = 0xE4, + MSM_DUMP_DATA_DBGUI_REG = 0xE5, + MSM_DUMP_DATA_DCC_REG = 0xE6, + MSM_DUMP_DATA_DCC_SRAM = 0xE7, + MSM_DUMP_DATA_MISC = 0xE8, + MSM_DUMP_DATA_VSENSE = 0xE9, + MSM_DUMP_DATA_RPM = 0xEA, + MSM_DUMP_DATA_SCANDUMP = 0xEB, + MSM_DUMP_DATA_RPMH = 0xEC, + MSM_DUMP_DATA_TMC_ETF = 0xF0, + MSM_DUMP_DATA_TMC_ETF_SWAO = 0xF1, + MSM_DUMP_DATA_TMC_REG = 0x100, + MSM_DUMP_DATA_TMC_ETF_SWAO_REG = 0x102, + MSM_DUMP_DATA_LOG_BUF = 0x110, + MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111, + MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130, + MSM_DUMP_DATA_LLCC_PER_INSTANCE = 0x140, + MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_table_ids { + MSM_DUMP_TABLE_APPS, + MSM_DUMP_TABLE_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_type { + MSM_DUMP_TYPE_DATA, + MSM_DUMP_TYPE_TABLE, +}; + +struct msm_dump_data { + uint32_t version; + uint32_t magic; + char name[32]; + uint64_t addr; + uint64_t len; + uint32_t reserved; +}; + +struct msm_dump_entry { + uint32_t id; + char name[32]; + uint32_t type; + uint64_t addr; +}; + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +extern int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +#else +static inline int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +static inline int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +#endif + +#endif From 04927aa32c487110a30ff2d98de7509725584884 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 12 Jan 2026 11:30:00 +0800 Subject: [PATCH 0006/1058] QCLINUX: mem-dump: add memory dump device driver Create memory dump device driver for matching the memory dump v2 driver without DT configuration. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/firmware/qcom/Kconfig | 6 + drivers/firmware/qcom/Makefile | 1 + drivers/firmware/qcom/memory_dump_dev.c | 379 ++++++++++++++++++++++ drivers/firmware/qcom/memory_dump_v2.c | 67 ++-- include/linux/firmware/qcom/memory_dump.h | 13 + 6 files changed, 420 insertions(+), 47 deletions(-) create mode 100644 drivers/firmware/qcom/memory_dump_dev.c diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 2e85e8df0469b..d50f78f3a3ea2 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,3 +1,4 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 531c6d2598ce0..39f63ef92e01a 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -83,4 +83,10 @@ config QCOM_MEMORY_DUMP_V2 of deadlocks or cpu hangs these dump regions are captured to give a snapshot of the system at the time of the crash. +config QCOM_MEMORY_DUMP_DEV + tristate "QCOM Memory Dump V2 device stub" + depends on QCOM_MEMORY_DUMP_V2 + help + Device stub for memory dump V2 driver. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index c5e17ba255937..01b293cae79ed 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_DEV) += memory_dump_dev.o diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c new file mode 100644 index 0000000000000..556ebafae5280 --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#define DEV_NAME "msm_mem_dump" + +static struct platform_device *mem_dump_pdev; + +enum dump_ids { + C0_CONTEXT = 0x0, + C100_CONTEXT = 0x1, + C200_CONTEXT = 0x2, + C300_CONTEXT = 0x3, + C400_CONTEXT = 0x4, + C500_CONTEXT = 0x5, + C600_CONTEXT = 0x6, + C700_CONTEXT = 0x7, + L1_ITLB10000 = 0x24, + L1_ITLB10100 = 0x25, + L1_ITLB10200 = 0x26, + L1_ITLB10300 = 0x27, + L1_DTLB10000 = 0x44, + L1_DTLB10100 = 0x45, + L1_DTLB10200 = 0x46, + L1_DTLB10300 = 0x47, + L1_ICACHE0 = 0x60, + L1_ICACHE100 = 0x61, + L1_ICACHE200 = 0x62, + L1_ICACHE300 = 0x63, + L1_ICACHE10000 = 0x64, + L1_ICACHE10100 = 0x65, + L1_ICACHE10200 = 0x66, + L1_ICACHE10300 = 0x67, + L1_DCACHE0 = 0x80, + L1_DCACHE100 = 0x81, + L1_DCACHE200 = 0x82, + L1_DCACHE300 = 0x83, + L1_DCACHE10000 = 0x84, + L1_DCACHE10100 = 0x85, + L1_DCACHE10200 = 0x86, + L1_DCACHE10300 = 0x87, + L2_CACHE10000 = 0xc4, + L2_CACHE10100 = 0xc5, + L2_CACHE10200 = 0xc6, + L2_CACHE10300 = 0xc7, + PMIC = 0xe4, + MISC_DATA = 0xe8, + RPM_SW = 0xea, + RPMH = 0xec, + CPUSS_REG = 0xef, + TMC_ETF = 0xf0, + ETF_SWAO = 0xf1, + ETF_LPASS = 0xf4, + FCM = 0xee, + ETR_REG = 0x100, + ETF_REG = 0x101, + ETFSWAO_REG = 0x102, + ETFLPASS_REG = 0x104, + L2_TLB0 = 0x120, + L2_TLB100 = 0x121, + L2_TLB200 = 0x122, + L2_TLB300 = 0x123, + L2_TLB10000 = 0x124, + L2_TLB10100 = 0x125, + L2_TLB10200 = 0x126, + L2_TLB10300 = 0x127, + C0_SCANDUMP = 0x130, + C100_SCANDUMP = 0x131, + C200_SCANDUMP = 0x132, + C300_SCANDUMP = 0x133, + C10000_SCANDUMP = 0x134, + C10100_SCANDUMP = 0x135, + C10200_SCANDUMP = 0x136, + C10300_SCANDUMP = 0x137, + LLCC1_D_CACHE = 0x140, + LLCC2_D_CACHE = 0x141, + MHM_SCAN = 0x161, + GEMNOC = 0x162, + OSM_REG = 0x163, + PCU_REG = 0x164, + FSM_DATA = 0x165, +}; + +static const struct dump_item lemans_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x40000, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x40000, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x40000, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10000_SCANDUMP, 0x40000, "c10000-scandump" }, + { C10100_SCANDUMP, 0x40000, "c10100-scandump" }, + { C10200_SCANDUMP, 0x40000, "c10200-scandump" }, + { C10300_SCANDUMP, 0x40000, "c10300-scandump" }, + { CPUSS_REG, 0x20000, "cpuss-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { L1_DCACHE0, 0x12100, "l1-dcache0" }, + { L1_DCACHE100, 0x12100, "l1-dcache100" }, + { L1_DCACHE200, 0x12100, "l1-dcache200" }, + { L1_DCACHE300, 0x12100, "l1-dcache300" }, + { L1_DCACHE10000, 0x12100, "l1-dcache10000" }, + { L1_DCACHE10100, 0x12100, "l1-dcache10100" }, + { L1_DCACHE10200, 0x12100, "l1-dcache10200" }, + { L1_DCACHE10300, 0x12100, "l1-dcache10300" }, + { L1_DTLB10000, 0x300, "l1-dtlb10000" }, + { L1_DTLB10100, 0x300, "l1-dtlb10100" }, + { L1_DTLB10200, 0x300, "l1-dtlb10200" }, + { L1_DTLB10300, 0x300, "l1-dtlb10300" }, + { L1_ICACHE0, 0x26100, "l1-icache0" }, + { L1_ICACHE100, 0x26100, "l1-icache100" }, + { L1_ICACHE200, 0x26100, "l1-icache200" }, + { L1_ICACHE300, 0x26100, "l1-icache300" }, + { L1_ICACHE10000, 0x26100, "l1-icache10000" }, + { L1_ICACHE10100, 0x26100, "l1-icache10100" }, + { L1_ICACHE10200, 0x26100, "l1-icache10200" }, + { L1_ICACHE10300, 0x26100, "l1-icache10300" }, + { L1_ITLB10000, 0x300, "l1-itlb10000" }, + { L1_ITLB10100, 0x300, "l1-itlb10100" }, + { L1_ITLB10200, 0x300, "l1-itlb10200" }, + { L1_ITLB10300, 0x300, "l1-itlb10300" }, + { L2_CACHE10000, 0x90100, "l2-cache10000" }, + { L2_CACHE10100, 0x90100, "l2-cache10100" }, + { L2_CACHE10200, 0x90100, "l2-cache10200" }, + { L2_CACHE10300, 0x90100, "l2-cache10300" }, + { L2_TLB0, 0x6100, "l2-tlb0" }, + { L2_TLB100, 0x6100, "l2-tlb100" }, + { L2_TLB200, 0x6100, "l2-tlb200" }, + { L2_TLB300, 0x6100, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb10000" }, + { L2_TLB10100, 0x6100, "l2-tlb10100" }, + { L2_TLB10200, 0x6100, "l2-tlb10200" }, + { L2_TLB10300, 0x6100, "l2-tlb10300" }, + { MISC_DATA, 0x1000, "misc-data" }, + { PMIC, 0x80000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_item talos_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x2000000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x10000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETF_SWAO, 0x8000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { L1_ICACHE0, 0x8800, "l1-icache0" }, + { L1_ICACHE100, 0x8800, "l1-icache100" }, + { L1_ICACHE200, 0x8800, "l1-icache200" }, + { L1_ICACHE300, 0x8800, "l1-icache300" }, + { L1_ICACHE10000, 0x8800, "l1-icache400" }, + { L1_ICACHE10100, 0x8800, "l1-icache500" }, + { L1_ICACHE10200, 0x11000, "l1-icache600" }, + { L1_ICACHE10300, 0x11000, "l1-icache700" }, + { L1_DCACHE0, 0x9000, "l1-dcache0" }, + { L1_DCACHE100, 0x9000, "l1-dcache100" }, + { L1_DCACHE200, 0x9000, "l1-dcache200" }, + { L1_DCACHE300, 0x9000, "l1-dcache300" }, + { L1_DCACHE10000, 0x9000, "l1-dcache400" }, + { L1_DCACHE10100, 0x9000, "l1-dcache500" }, + { L1_DCACHE10200, 0x12000, "l1-dcache600" }, + { L1_DCACHE10300, 0x12000, "l1-dcache700" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x300, "l1-itlb700" }, + { L1_DTLB10200, 0x480, "l1-dtlb600" }, + { L1_DTLB10300, 0x480, "l1-dtlb700" }, + { L2_CACHE10200, 0x48000, "l2-cache600" }, + { L2_CACHE10300, 0x48000, "l2-cache700" }, + { L2_TLB0, 0x5000, "l2-tlb0" }, + { L2_TLB100, 0x5000, "l2-tlb100" }, + { L2_TLB200, 0x5000, "l2-tlb200" }, + { L2_TLB300, 0x5000, "l2-tlb300" }, + { L2_TLB10000, 0x5000, "l2-tlb400" }, + { L2_TLB10100, 0x5000, "l2-tlb500" }, + { L2_TLB10200, 0x7800, "l2-tlb600" }, + { L2_TLB10300, 0x7800, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x6c000, "llcc1-d-cache" }, +}; + +static const struct dump_item kodiak_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x10100, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x10100, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x10100, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x10100, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C10000_SCANDUMP, 0x40000, "c400-scandump" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C10100_SCANDUMP, 0x40000, "c500-scandump" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C10200_SCANDUMP, 0x40000, "c600-scandump" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10300_SCANDUMP, 0x40000, "c700-scandump" }, + { CPUSS_REG, 0x30000, "cpuss-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { FSM_DATA, 0x400, "fsm-data" }, + { GEMNOC, 0x100000, "gemnoc" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L1_DCACHE10000, 0x9100, "l1-dcache400" }, + { L1_DCACHE10100, 0x9100, "l1-dcache500" }, + { L1_DCACHE10200, 0x9100, "l1-dcache600" }, + { L1_DCACHE10300, 0x12100, "l1-dcache700" }, + { L1_DTLB10000, 0x300, "l1-dtlb400" }, + { L1_DTLB10100, 0x300, "l1-dtlb500" }, + { L1_DTLB10200, 0x300, "l1-dtlb600" }, + { L1_DTLB10300, 0x3a0, "l1-dtlb700" }, + { L1_ICACHE0, 0x10900, "l1-icache0" }, + { L1_ICACHE100, 0x10900, "l1-icache100" }, + { L1_ICACHE200, 0x10900, "l1-icache200" }, + { L1_ICACHE300, 0x10900, "l1-icache300" }, + { L1_ICACHE10000, 0x15100, "l1-icache400" }, + { L1_ICACHE10100, 0x15100, "l1-icache500" }, + { L1_ICACHE10200, 0x15100, "l1-icache600" }, + { L1_ICACHE10300, 0x32100, "l1-icache700" }, + { L1_ITLB10000, 0x300, "l1-itlb400" }, + { L1_ITLB10100, 0x300, "l1-itlb500" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x400, "l1-itlb700" }, + { L2_CACHE10000, 0x90100, "l2-cache400" }, + { L2_CACHE10100, 0x90100, "l2-cache500" }, + { L2_CACHE10200, 0x90100, "l2-cache600" }, + { L2_CACHE10300, 0x120100, "l2-cache700" }, + { L2_TLB0, 0x5b00, "l2-tlb0" }, + { L2_TLB100, 0x5b00, "l2-tlb100" }, + { L2_TLB200, 0x5b00, "l2-tlb200" }, + { L2_TLB300, 0x5b00, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb400" }, + { L2_TLB10100, 0x6100, "l2-tlb500" }, + { L2_TLB10200, 0x6100, "l2-tlb600" }, + { L2_TLB10300, 0xc100, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x1141c0, "llcc1-d-cache" }, + { LLCC2_D_CACHE, 0x1141c0, "llcc2-d-cache" }, + { MHM_SCAN, 0x20000, "mhm-scan" }, + { MISC_DATA, 0x1000, "misc-data" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { PMIC, 0x200000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_table lemans_dump_table = { + .items = lemans_items, + .num_of_items = ARRAY_SIZE(lemans_items), + .imem_base = 0x146d8010, + .imem_size = 0x8, +}; + +static const struct dump_table talos_dump_table = { + .items = talos_items, + .num_of_items = ARRAY_SIZE(lemans_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static const struct dump_table kodiak_dump_table = { + .items = kodiak_items, + .num_of_items = ARRAY_SIZE(kodiak_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static int __init mem_dump_dev_init(void) +{ + int ret; + u32 soc_id; + + mem_dump_pdev = platform_device_alloc(DEV_NAME, -1); + if (!mem_dump_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(mem_dump_pdev, + &talos_dump_table, sizeof(talos_dump_table)); + if (ret) + goto fail; + + break; + case 534: + case 606: + case 667: + case 674: + case 675: + case 676: + ret = platform_device_add_data(mem_dump_pdev, + &lemans_dump_table, sizeof(lemans_dump_table)); + if (ret) + goto fail; + + break; + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(mem_dump_pdev, + &kodiak_dump_table, sizeof(kodiak_dump_table)); + if (ret) + goto fail; + + break; + default: + dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(mem_dump_pdev); + if (ret) + goto fail; + + dev_info(&mem_dump_pdev->dev, "Register platform device successfully\n"); + + return 0; + +fail: + dev_err(&mem_dump_pdev->dev, + "Failed to register memory dump platform device\n"); + platform_device_put(mem_dump_pdev); + + return ret; +} + +static void __exit mem_dump_dev_exit(void) +{ + platform_device_unregister(mem_dump_pdev); +} + +module_init(mem_dump_dev_init); +module_exit(mem_dump_dev_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. Memory Dump driver V2, device stub"); diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index baf4c980f39fb..470d6047ee656 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -865,19 +865,11 @@ int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, EXPORT_SYMBOL_GPL(msm_dump_data_register_nominidump); #define MSM_DUMP_TOTAL_SIZE_OFFSET 0x724 -static int init_memdump_imem_area(size_t size) +static int init_memdump_imem_area(const struct dump_table *table, size_t size) { - struct device_node *np; void __iomem *imem_base; - np = of_find_compatible_node(NULL, NULL, - "qcom,msm-imem-mem-dump-table"); - if (!np) { - pr_err("mem dump base table DT node does not exist\n"); - return -ENODEV; - } - - imem_base = of_iomap(np, 0); + imem_base = ioremap(table->imem_base, table->imem_size); if (!imem_base) { pr_err("mem dump base table imem offset mapping failed\n"); return -ENOMEM; @@ -924,13 +916,17 @@ static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) static int mem_dump_reserve_mem(struct device *dev) { struct device_node *mem_node; + struct reserved_mem *rmem; int ret; - mem_node = of_parse_phandle(dev->of_node, "memory-region", 0); + mem_node = of_find_node_by_path("/reserved-memory/mem-dump-region"); if (mem_node) { - ret = of_reserved_mem_device_init_by_idx(dev, - dev->of_node, 0); - of_node_put(dev->of_node); + rmem = of_reserved_mem_lookup(mem_node); + of_node_put(mem_node); + if (!rmem || !rmem->ops || !rmem->ops->device_init) + return -EINVAL; + + ret = rmem->ops->device_init(rmem, dev); if (ret) { dev_err(dev, "Failed to initialize reserved mem, ret %d\n", @@ -1005,34 +1001,26 @@ static int cpuss_dump_init(struct platform_device *pdev, #define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) static int mem_dump_alloc(struct platform_device *pdev) { - struct device_node *child_node; - const struct device_node *node = pdev->dev.of_node; struct msm_dump_data *dump_data; struct msm_dump_entry dump_entry; size_t total_size; u32 size, id; - int ret, no_of_nodes; + int i, ret, no_of_nodes; dma_addr_t dma_handle; phys_addr_t phys_addr; struct sg_table mem_dump_sgt; void *dump_vaddr; u64 shm_bridge_handle; int initialized = 0; + const struct dump_table *table = dev_get_platdata(&pdev->dev); if (mem_dump_reserve_mem(&pdev->dev) != 0) return -ENOMEM; total_size = size = ret = no_of_nodes = 0; /* For dump table registration with IMEM */ total_size = sizeof(struct msm_dump_table) * 2; - for_each_available_child_of_node(node, child_node) { - ret = of_property_read_u32(child_node, "qcom,dump-size", &size); - if (ret) { - dev_err(&pdev->dev, "Unable to find size for %s\n", - child_node->name); - continue; - } - - total_size += size; + for (i = 0; i < table->num_of_items; i++) { + total_size += table->items[i].size; no_of_nodes++; } @@ -1062,7 +1050,7 @@ static int mem_dump_alloc(struct platform_device *pdev) return ret; } - ret = init_memdump_imem_area(total_size); + ret = init_memdump_imem_area(table, total_size); if (ret) { qcom_tzmem_shm_bridge_delete(shm_bridge_handle); return ret; @@ -1070,24 +1058,15 @@ static int mem_dump_alloc(struct platform_device *pdev) dump_vaddr += (sizeof(struct msm_dump_table) * 2); phys_addr += (sizeof(struct msm_dump_table) * 2); - for_each_available_child_of_node(node, child_node) { - ret = of_property_read_u32(child_node, "qcom,dump-size", &size); - if (ret) - continue; - - ret = of_property_read_u32(child_node, "qcom,dump-id", &id); - if (ret) { - dev_err(&pdev->dev, "Unable to find id for %s\n", - child_node->name); - continue; - } - + for (i = 0; i < table->num_of_items; i++) { + size = table->items[i].size; + id = table->items[i].dump_id; dump_data = dump_vaddr; dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; dump_data->len = size; dump_entry.id = id; - strscpy(dump_data->name, child_node->name, - sizeof(dump_data->name)); + strscpy(dump_data->name, table->items[i].name, + sizeof(table->items[i].name)); dump_entry.addr = phys_addr; ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, &dump_entry); @@ -1124,16 +1103,10 @@ static int mem_dump_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id mem_dump_match_table[] = { - {.compatible = "qcom,mem-dump",}, - {} -}; - static struct platform_driver mem_dump_driver = { .probe = mem_dump_probe, .driver = { .name = "msm_mem_dump", - .of_match_table = mem_dump_match_table, }, }; diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h index ebb7c89d2f243..e72436feb0544 100644 --- a/include/linux/firmware/qcom/memory_dump.h +++ b/include/linux/firmware/qcom/memory_dump.h @@ -115,6 +115,19 @@ struct msm_dump_entry { uint64_t addr; }; +struct dump_item { + u32 dump_id; + size_t size; + const char *name; +}; + +struct dump_table { + const struct dump_item *items; + u32 num_of_items; + phys_addr_t imem_base; + resource_size_t imem_size; +}; + #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) extern int msm_dump_data_register(enum msm_dump_table_ids id, struct msm_dump_entry *entry); From 75ec75270f66ec30923cdf604105a1a00b092cc6 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Feb 2026 18:16:25 +0800 Subject: [PATCH 0007/1058] QCLINUX: memory-dump: add logic for reserving CMA memory Memory dump driver needs a large CMA memory zone for storing memory dump table. Add codes for reserving CMA memory during the init stage. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 2 +- arch/arm64/mm/init.c | 4 ++ drivers/firmware/qcom/Kconfig | 1 + drivers/firmware/qcom/memory_dump_v2.c | 58 +++++++++-------------- include/linux/firmware/qcom/memory_dump.h | 4 +- 5 files changed, 31 insertions(+), 38 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index d50f78f3a3ea2..48ae2fb9737ac 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m -CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 96711b8578fd0..dae135db3845e 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -48,6 +48,7 @@ #include #include #include +#include /* * We need to be able to catch inadvertent references to memstart_addr @@ -324,6 +325,9 @@ void __init bootmem_init(void) * reserved, so do it here. */ arch_reserve_crashkernel(); +#if defined(CONFIG_QCOM_MEMORY_DUMP_V2) + reserve_memdump_cma(); +#endif memblock_dump_all(); } diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 39f63ef92e01a..dd20fed163e3f 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -77,6 +77,7 @@ config QCOM_QSEECOM_UEFISECAPP config QCOM_MEMORY_DUMP_V2 tristate "QCOM Memory Dump V2 Support" depends on QCOM_TZMEM + depends on CMA help This enables memory dump feature. It allows various client subsystems to register respective dump regions. At the time diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index 470d6047ee656..831d1aea86e09 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -18,6 +18,10 @@ #include #include #include +#include +#include +#include +#include #define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) @@ -913,30 +917,6 @@ static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) return 0; } -static int mem_dump_reserve_mem(struct device *dev) -{ - struct device_node *mem_node; - struct reserved_mem *rmem; - int ret; - - mem_node = of_find_node_by_path("/reserved-memory/mem-dump-region"); - if (mem_node) { - rmem = of_reserved_mem_lookup(mem_node); - of_node_put(mem_node); - if (!rmem || !rmem->ops || !rmem->ops->device_init) - return -EINVAL; - - ret = rmem->ops->device_init(rmem, dev); - if (ret) { - dev_err(dev, - "Failed to initialize reserved mem, ret %d\n", - ret); - return ret; - } - } - return 0; -} - static int cpuss_regdump_init(struct device *dev, void *dump_vaddr, u32 size) { @@ -998,6 +978,18 @@ static int cpuss_dump_init(struct platform_device *pdev, return initialized; } +struct cma *memdump_cma; +void __init reserve_memdump_cma(void) +{ + unsigned long long cma_size = 0x3000000; + unsigned long long request_size = roundup(cma_size, PAGE_SIZE); + + if (cma_declare_contiguous(0, request_size, 0, 0, 0, false, + "memdump", &memdump_cma)) { + pr_warn("memdump CMA reservation failed\n"); + } +} + #define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) static int mem_dump_alloc(struct platform_device *pdev) { @@ -1006,16 +998,13 @@ static int mem_dump_alloc(struct platform_device *pdev) size_t total_size; u32 size, id; int i, ret, no_of_nodes; - dma_addr_t dma_handle; phys_addr_t phys_addr; - struct sg_table mem_dump_sgt; void *dump_vaddr; u64 shm_bridge_handle; int initialized = 0; const struct dump_table *table = dev_get_platdata(&pdev->dev); + struct page *reserved_page; - if (mem_dump_reserve_mem(&pdev->dev) != 0) - return -ENOMEM; total_size = size = ret = no_of_nodes = 0; /* For dump table registration with IMEM */ total_size = sizeof(struct msm_dump_table) * 2; @@ -1026,15 +1015,12 @@ static int mem_dump_alloc(struct platform_device *pdev) total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); total_size = ALIGN(total_size, SZ_4K); - dump_vaddr = dmam_alloc_coherent(&pdev->dev, total_size, - &dma_handle, GFP_KERNEL); - if (!dump_vaddr) + reserved_page = cma_alloc(memdump_cma, total_size >> PAGE_SHIFT, + 0, false); + if (!reserved_page) return -ENOMEM; - - dma_get_sgtable(&pdev->dev, &mem_dump_sgt, dump_vaddr, - dma_handle, total_size); - phys_addr = page_to_phys(sg_page(mem_dump_sgt.sgl)); - sg_free_table(&mem_dump_sgt); + phys_addr = page_to_phys(reserved_page); + dump_vaddr = page_to_virt(reserved_page); memset(dump_vaddr, 0x0, total_size); ret = qcom_tzmem_shm_bridge_create(phys_addr, total_size, &shm_bridge_handle); diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h index e72436feb0544..ead7add4265c5 100644 --- a/include/linux/firmware/qcom/memory_dump.h +++ b/include/linux/firmware/qcom/memory_dump.h @@ -33,6 +33,9 @@ struct msm_client_dump { unsigned long end_addr; }; +void __init reserve_memdump_cma(void); +extern struct cma *memdump_cma; + #ifdef CONFIG_QCOM_MEMORY_DUMP extern int msm_dump_tbl_register(struct msm_client_dump *client_entry); #else @@ -42,7 +45,6 @@ static inline int msm_dump_tbl_register(struct msm_client_dump *entry) } #endif - #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) extern uint32_t msm_dump_table_version(void); #else From 59765f2430fbbe05a5efe05ae48c4ca2d928af69 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 13:44:34 +0800 Subject: [PATCH 0008/1058] QCLINUX: qcom-dcc: add device configuration for Pakala Add device configuration to enable DCC on Pakala platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index e0eb2e61d652b..0c2369a4843ae 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -39,6 +39,15 @@ static const struct dcc_pdata kodiak_pdata = { .map_ver = 0x2, }; +static const struct dcc_pdata pakala_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10084000, + .ram_size = 0x4000, + .dcc_offset = 0x4000, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -83,6 +92,15 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(dcc_pdev, &pakala_pdata, sizeof(pakala_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From f97d300738f8b3d62bc44ebe5e11f7af43cdd4c8 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 14:10:29 +0800 Subject: [PATCH 0009/1058] QCLINUX: memory-dump: add memory dump table for Pakala Add memory dump table configuration to enable memory dump function on Pakala platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 50 +++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 556ebafae5280..1626a67017990 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -57,12 +57,15 @@ enum dump_ids { CPUSS_REG = 0xef, TMC_ETF = 0xf0, ETF_SWAO = 0xf1, + ETF_SLPI = 0xf3, ETF_LPASS = 0xf4, FCM = 0xee, ETR_REG = 0x100, ETF_REG = 0x101, ETFSWAO_REG = 0x102, + ETFSLPI_REG = 0x103, ETFLPASS_REG = 0x104, + ETR1_REG = 0x105, L2_TLB0 = 0x120, L2_TLB100 = 0x121, L2_TLB200 = 0x122, @@ -86,6 +89,7 @@ enum dump_ids { OSM_REG = 0x163, PCU_REG = 0x164, FSM_DATA = 0x165, + SCANDUMP_SMMU = 0x220, }; static const struct dump_item lemans_items[] = { @@ -277,6 +281,35 @@ static const struct dump_item kodiak_items[] = { { RPMH, 0x2000000, "rpmh" }, }; +static const struct dump_item pakala_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -298,6 +331,13 @@ static const struct dump_table kodiak_dump_table = { .imem_size = 0x8, }; +static const struct dump_table pakala_dump_table = { + .items = pakala_items, + .num_of_items = ARRAY_SIZE(pakala_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -345,6 +385,16 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(mem_dump_pdev, + &pakala_dump_table, sizeof(pakala_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From f1d5623f0115bd29c040a7936159dc0f6ac8d62b Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 14:58:04 +0800 Subject: [PATCH 0010/1058] QCLINUX: qcom-dcc: add device configuration for Kaanapali Add device configuration to enable DCC on Kaanapali platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 0c2369a4843ae..5ed2a117b9e81 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -48,6 +48,15 @@ static const struct dcc_pdata pakala_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata kaanapali_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -101,6 +110,18 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(dcc_pdev, &kaanapali_pdata, sizeof(kaanapali_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From 456b9522d0a1b7af0a215dddab2617d1720f7b3d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:16:19 +0800 Subject: [PATCH 0011/1058] QCLINUX: memory-dump: add memory dump table for Kaanapali Add memory dump table configuration to enable memory dump function on Kaanapali platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 1626a67017990..d02e6af6c03a0 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -310,6 +310,35 @@ static const struct dump_item pakala_items[] = { { C0_SCANDUMP, 0x380000, "apps-scandump" }, }; +static const struct dump_item kaanapali_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -338,6 +367,13 @@ static const struct dump_table pakala_dump_table = { .imem_size = 0x8, }; +static const struct dump_table kaanapali_dump_table = { + .items = kaanapali_items, + .num_of_items = ARRAY_SIZE(kaanapali_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -395,6 +431,19 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(mem_dump_pdev, + &kaanapali_dump_table, sizeof(kaanapali_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From 49a40c40824ddef7f7ad4b9884cdf5e65bd01c0f Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:32:10 +0800 Subject: [PATCH 0012/1058] QCLINUX: qcom-dcc: add device configuration for Hamoa Add device configuration to enable DCC on Hamoa platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 5ed2a117b9e81..ff19dac70011f 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -57,6 +57,15 @@ static const struct dcc_pdata kaanapali_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata hamoa_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x18000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -122,6 +131,16 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 555: + case 615: + case 616: + case 709: + case 710: + ret = platform_device_add_data(dcc_pdev, &hamoa_pdata, sizeof(hamoa_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From 281d564aa046eb9cea6f4ab86bfe8c70e1858b36 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:45:31 +0800 Subject: [PATCH 0013/1058] QCLINUX: memory-dump: add memory dump table for Hamoa Add memory dump table configuration to enable memory dump function on Hamoa platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index d02e6af6c03a0..0f89cb201b783 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -339,6 +339,22 @@ static const struct dump_item kaanapali_items[] = { { C0_SCANDUMP, 0x380000, "apps-scandump" }, }; +static const struct dump_item hamoa_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0xc10000, "rpmh" }, + { PMIC, 0x200000, "pmic" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -374,6 +390,13 @@ static const struct dump_table kaanapali_dump_table = { .imem_size = 0x8, }; +static const struct dump_table hamoa_dump_table = { + .items = hamoa_items, + .num_of_items = ARRAY_SIZE(hamoa_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -444,6 +467,17 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 555: + case 615: + case 616: + case 709: + case 710: + ret = platform_device_add_data(mem_dump_pdev, + &hamoa_dump_table, sizeof(hamoa_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From b3bff1d52bdf75862574b137b433e7541ce1637b Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 4 Mar 2026 09:15:02 +0800 Subject: [PATCH 0014/1058] QCLINUX: memory-dump: fix array size issue for Talos Fix the wrong arrary size issue for Talos. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0f89cb201b783..78fb377800bc9 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -364,7 +364,7 @@ static const struct dump_table lemans_dump_table = { static const struct dump_table talos_dump_table = { .items = talos_items, - .num_of_items = ARRAY_SIZE(lemans_items), + .num_of_items = ARRAY_SIZE(talos_items), .imem_base = 0x146aa010, .imem_size = 0x8, }; From ec6e14e1fe9c34f76a715ce17cfbba7595d86e81 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Mar 2026 15:23:32 +0800 Subject: [PATCH 0015/1058] QCLINUX: qcom-dcc: add device configuration for Glymur Add device configuration to enable DCC on Glymur platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index ff19dac70011f..5da18b4d221dd 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -66,6 +66,15 @@ static const struct dcc_pdata hamoa_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata glymur_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -141,6 +150,16 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 662: + case 698: + case 699: + case 718: + case 719: + ret = platform_device_add_data(dcc_pdev, &glymur_pdata, sizeof(glymur_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From 342aeb8c5a4125bff7f8431acf4b6f8b73920dd9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Mar 2026 15:14:07 +0800 Subject: [PATCH 0016/1058] QCLINUX: memory-dump: add support for Glymur Glymur is sharing the same dump table content with Hamoa. So add Glymur's chip IDs for registering the dump table in memory. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 78fb377800bc9..0c0cb06462cc5 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -468,11 +468,18 @@ static int __init mem_dump_dev_init(void) goto fail; break; + /* Hamoa chip IDs */ case 555: case 615: case 616: case 709: case 710: + /* Glymur chip IDs */ + case 662: + case 698: + case 699: + case 718: + case 719: ret = platform_device_add_data(mem_dump_pdev, &hamoa_dump_table, sizeof(hamoa_dump_table)); if (ret) From b443c9635c8c61d7a660dbd69c8e81eeeb3b6362 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 14:15:20 +0800 Subject: [PATCH 0017/1058] QCLINUX: qcom-dcc: add logic to configure linked list in probe Configure the linked list with defined register entries in dcc_probe. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 38 +++++++++++++++++++++ drivers/misc/qcom-dcc.c | 67 +++++++++++++++++++++++++++++++++++++ drivers/misc/qcom-dcc.h | 16 +++++++++ 3 files changed, 121 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 5da18b4d221dd..52571a2a6228e 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -12,6 +12,24 @@ static struct platform_device *dcc_pdev; +static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x3d96000" }, + { "R 0x3d96004" }, +}; + +static const struct dcc_link_config talos_link_configs[] = { + { + .link_list = 3, + .entries = talos_dcc_entries, + .num_entries = ARRAY_SIZE(talos_dcc_entries), + }, +}; + +static const struct dcc_config talos_config = { + .lists = talos_link_configs, + .num_lists = ARRAY_SIZE(talos_link_configs), +}; + static const struct dcc_pdata talos_pdata = { .base = 0x010a2000, .size = 0x00001000, @@ -19,6 +37,25 @@ static const struct dcc_pdata talos_pdata = { .ram_size = 0x00002000, .dcc_offset = 0x6000, .map_ver = 0x1, + .config = &talos_config, +}; + +static const struct dcc_register_entry lemans_dcc_entries[] = { + { "R 0x610110 1" }, + { "R 0x9050008 1" }, +}; + +static const struct dcc_link_config lemans_link_configs[] = { + { + .link_list = 6, + .entries = lemans_dcc_entries, + .num_entries = ARRAY_SIZE(lemans_dcc_entries), + }, +}; + +static const struct dcc_config lemans_config = { + .lists = lemans_link_configs, + .num_lists = ARRAY_SIZE(lemans_link_configs), }; static const struct dcc_pdata lemans_pdata = { @@ -28,6 +65,7 @@ static const struct dcc_pdata lemans_pdata = { .ram_size = 0x00006000, .dcc_offset = 0x38800, .map_ver = 0x3, + .config = &lemans_config, }; static const struct dcc_pdata kodiak_pdata = { diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c index e75f98b90d8f7..d38c5f4a680b6 100644 --- a/drivers/misc/qcom-dcc.c +++ b/drivers/misc/qcom-dcc.c @@ -1425,6 +1425,72 @@ static ssize_t dcc_sram_read(struct file *file, char __user *data, return len; } +static void dcc_configure_list(struct dcc_drvdata *drvdata, + const struct dcc_config *config) +{ + const struct dcc_link_config *link; + const struct dcc_register_entry *entry; + char *token, *bufp, *buf_orig; + char *delim = " "; + int ret, i, j, configured; + size_t len; + + if (!config || !config->num_lists) + return; + + for (i = 0; i < config->num_lists; i++) { + link = &config->lists[i]; + + if (link->link_list >= drvdata->max_link_list) { + dev_err(drvdata->dev, "Invalid link list index %d\n", link->link_list); + continue; + } + + configured = 0; + + for (j = 0; j < link->num_entries; j++) { + entry = &link->entries[j]; + + len = strlen(entry->config); + buf_orig = kzalloc(len + 1, GFP_KERNEL); + if (!buf_orig) + return; + + strscpy(buf_orig, entry->config, len + 1); + bufp = buf_orig; + + token = strsep(&bufp, delim); + if (!bufp) { + dev_err(drvdata->dev, "Malformed entry: \"%s\"\n", + entry->config); + kfree(buf_orig); + continue; + } + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, bufp, link->link_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, bufp, link->link_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, bufp, link->link_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, bufp, link->link_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret >= 0) + configured++; + + kfree(buf_orig); + } + + if (configured) + dcc_enable(drvdata, link->link_list); + } +} + static const struct file_operations dcc_sram_fops = { .owner = THIS_MODULE, .read = dcc_sram_read, @@ -1520,6 +1586,7 @@ static int dcc_probe(struct platform_device *pdev) } dcc_create_debug_dir(drvdata); + dcc_configure_list(drvdata, pdata->config); return 0; } diff --git a/drivers/misc/qcom-dcc.h b/drivers/misc/qcom-dcc.h index 513c95dc742b5..ce8551141062d 100644 --- a/drivers/misc/qcom-dcc.h +++ b/drivers/misc/qcom-dcc.h @@ -8,6 +8,21 @@ #include +struct dcc_register_entry { + const char *config; +}; + +struct dcc_link_config { + int link_list; + const struct dcc_register_entry *entries; + int num_entries; +}; + +struct dcc_config { + const struct dcc_link_config *lists; + int num_lists; +}; + struct dcc_pdata { phys_addr_t base; resource_size_t size; @@ -15,6 +30,7 @@ struct dcc_pdata { resource_size_t ram_size; u32 dcc_offset; u8 map_ver; + const struct dcc_config *config; }; #endif From 3a4648d380fc3d5f2a0396cce16714235705fb85 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 14:15:33 +0800 Subject: [PATCH 0018/1058] QCLINUX: qcom-dcc: add register list for the Talos Add the registers for configuring the linked_list of the DCC driver for debugging purpose. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 753 ++++++++++++++++++++++++++++++++++++ 1 file changed, 753 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 52571a2a6228e..7656e8e90aa1c 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -13,6 +13,759 @@ static struct platform_device *dcc_pdev; static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x9680000" }, + { "R 0x9680004" }, + { "R 0x9681000" }, + { "R 0x9681004" }, + { "R 0x9681008" }, + { "R 0x968100c" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x968101c" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102c" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103c" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812c" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813c" }, + { "R 0x9698500" }, + { "R 0x9698504" }, + { "R 0x9698508" }, + { "R 0x969850c" }, + { "R 0x9698510" }, + { "R 0x9698514" }, + { "R 0x9698518" }, + { "R 0x969851c" }, + { "R 0x9698700" }, + { "R 0x9698704" }, + { "R 0x9698708" }, + { "R 0x969870c" }, + { "R 0x9698714" }, + { "R 0x9698718" }, + { "R 0x969871c" }, + { "R 0x1620204" }, + { "R 0x1620240" }, + { "R 0x1620248" }, + { "R 0x1620288" }, + { "R 0x162028C" }, + { "R 0x1620290" }, + { "R 0x1620294" }, + { "R 0x16202A8" }, + { "R 0x16202AC" }, + { "R 0x16202B0" }, + { "R 0x16202B4" }, + { "R 0x1620300" }, + { "R 0x1700204" }, + { "R 0x1700240" }, + { "R 0x1700248" }, + { "R 0x1700288" }, + { "R 0x1700290" }, + { "R 0x1700300" }, + { "R 0x1700304" }, + { "R 0x1700308" }, + { "R 0x170030C" }, + { "R 0x1700310" }, + { "R 0x1700314" }, + { "R 0x1700C08" }, + { "R 0x1700C10" }, + { "R 0x1700C20" }, + { "R 0x1700C24" }, + { "R 0x1700C28" }, + { "R 0x1700C2C" }, + { "R 0x1700C30" }, + { "R 0x1700C34" }, + { "R 0x1700C38" }, + { "R 0x1700C3C" }, + { "R 0x1740240" }, + { "R 0x1740248" }, + { "R 0x1740288" }, + { "R 0x1740290" }, + { "R 0x1740300" }, + { "R 0x1740304" }, + { "R 0x1740308" }, + { "R 0x174030C" }, + { "R 0x1740310" }, + { "R 0x1740314" }, + { "R 0x1740004" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020" }, + { "R 0x1740024" }, + { "R 0x1740028" }, + { "R 0x174002C" }, + { "R 0x1740030" }, + { "R 0x1740034" }, + { "R 0x1740038" }, + { "R 0x174003C" }, + { "R 0x9698204" }, + { "R 0x9698240" }, + { "R 0x9698244" }, + { "R 0x9698248" }, + { "R 0x969824C" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x9681018" }, + { "R 0x968101C" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102C" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103C" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812C" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813C" }, + { "R 0x62BE2004" }, + { "R 0x62BE2040" }, + { "R 0x62BE2048" }, + { "R 0x62BE2088" }, + { "R 0x62BE2090" }, + { "R 0x62BE2100" }, + { "R 0x62BE2104" }, + { "R 0x62BE2108" }, + { "R 0x62BE210C" }, + { "R 0x62BE2110" }, + { "R 0x62BE2114" }, + { "R 0x62BE2118" }, + { "R 0x62BE0010" }, + { "R 0x62BE0020" }, + { "R 0x62BE0024" }, + { "R 0x62BE0028" }, + { "R 0x62BE002C" }, + { "R 0x62BE0030" }, + { "R 0x62BE0034" }, + { "R 0x62BE0038" }, + { "R 0x62BE003C" }, + { "R 0x9160204" }, + { "R 0x9160240" }, + { "R 0x9160248" }, + { "R 0x9160288" }, + { "R 0x9160290" }, + { "R 0x9160300" }, + { "R 0x9160304" }, + { "R 0x9160308" }, + { "R 0x916030C" }, + { "R 0x9160310" }, + { "R 0x9160314" }, + { "R 0x9160318" }, + { "R 0x9160008" }, + { "R 0x9160010" }, + { "R 0x9160020" }, + { "R 0x9160024" }, + { "R 0x9160028" }, + { "R 0x916002C" }, + { "R 0x9160030" }, + { "R 0x9160034" }, + { "R 0x9160038" }, + { "R 0x916003C" }, + { "R 0x1620500 4" }, + { "R 0x1620700 4" }, + { "R 0x1620300" }, + { "R 0x1620F00 2" }, + { "R 0x1620B00 2" }, + { "R 0x1700B00 2" }, + { "R 0x1700700 3" }, + { "R 0x9163100" }, + { "R 0x96AA100" }, + { "R 0x9050008" }, + { "R 0x9050068" }, + { "R 0x9050078" }, + { "R 0x18200400" }, + { "R 0x18200404" }, + { "R 0x18200408" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200D0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + { "R 0x1822000c" }, + { "R 0x18220d14" }, + { "R 0x18220fb4" }, + { "R 0x18221254" }, + { "R 0x182214f4" }, + { "R 0x18221794" }, + { "R 0x18221a34" }, + { "R 0x18221cd4" }, + { "R 0x18221f74" }, + { "R 0x18220d18" }, + { "R 0x18220fb8" }, + { "R 0x18221258" }, + { "R 0x182214f8" }, + { "R 0x18221798" }, + { "R 0x18221a38" }, + { "R 0x18221cd8" }, + { "R 0x18221f78" }, + { "R 0x18220d00" }, + { "R 0x18220d04" }, + { "R 0x18220d1c" }, + { "R 0x18220fbc" }, + { "R 0x1822125c" }, + { "R 0x182214fc" }, + { "R 0x1822179c" }, + { "R 0x18221a3c" }, + { "R 0x18221cdc" }, + { "R 0x18221f7c" }, + { "R 0x18221274" }, + { "R 0x18221288" }, + { "R 0x1822129c" }, + { "R 0x182212b0" }, + { "R 0x182212c4" }, + { "R 0x182212d8" }, + { "R 0x182212ec" }, + { "R 0x18221300" }, + { "R 0x18221314" }, + { "R 0x18221328" }, + { "R 0x1822133c" }, + { "R 0x18221350" }, + { "R 0x18221364" }, + { "R 0x18221378" }, + { "R 0x1822138c" }, + { "R 0x182213a0" }, + { "R 0x18221514" }, + { "R 0x18221528" }, + { "R 0x1822153c" }, + { "R 0x18221550" }, + { "R 0x18221564" }, + { "R 0x18221578" }, + { "R 0x1822158c" }, + { "R 0x182215a0" }, + { "R 0x182215b4" }, + { "R 0x182215c8" }, + { "R 0x182215dc" }, + { "R 0x182215f0" }, + { "R 0x18221604" }, + { "R 0x18221618" }, + { "R 0x1822162c" }, + { "R 0x18221640" }, + { "R 0x182217b4" }, + { "R 0x182217c8" }, + { "R 0x182217dc" }, + { "R 0x182217f0" }, + { "R 0x18221804" }, + { "R 0x18221818" }, + { "R 0x1822182c" }, + { "R 0x18221840" }, + { "R 0x18221854" }, + { "R 0x18221868" }, + { "R 0x1822187c" }, + { "R 0x18221890" }, + { "R 0x182218a4" }, + { "R 0x182218b8" }, + { "R 0x182218cc" }, + { "R 0x182218e0" }, + { "R 0x18221a54" }, + { "R 0x18221a68" }, + { "R 0x18221a7c" }, + { "R 0x18221a90" }, + { "R 0x18221aa4" }, + { "R 0x18221ab8" }, + { "R 0x18221acc" }, + { "R 0x18221ae0" }, + { "R 0x18221af4" }, + { "R 0x18221b08" }, + { "R 0x18221b1c" }, + { "R 0x18221b30" }, + { "R 0x18221b44" }, + { "R 0x18221b58" }, + { "R 0x18221b6c" }, + { "R 0x18221b80" }, + { "R 0x18221cf4" }, + { "R 0x18221d08" }, + { "R 0x18221d1c" }, + { "R 0x18221d30" }, + { "R 0x18221d44" }, + { "R 0x18221d58" }, + { "R 0x18221d6c" }, + { "R 0x18221d80" }, + { "R 0x18221d94" }, + { "R 0x18221da8" }, + { "R 0x18221dbc" }, + { "R 0x18221dd0" }, + { "R 0x18221de4" }, + { "R 0x18221df8" }, + { "R 0x18221e0c" }, + { "R 0x18221e20" }, + { "R 0x18221f94" }, + { "R 0x18221fa8" }, + { "R 0x18221fbc" }, + { "R 0x18221fd0" }, + { "R 0x18221fe4" }, + { "R 0x18221ff8" }, + { "R 0x1822200c" }, + { "R 0x18222020" }, + { "R 0x18222034" }, + { "R 0x18222048" }, + { "R 0x1822205c" }, + { "R 0x18222070" }, + { "R 0x18222084" }, + { "R 0x18222098" }, + { "R 0x182220ac" }, + { "R 0x182220c0" }, + { "R 0x18221278" }, + { "R 0x1822128c" }, + { "R 0x182212a0" }, + { "R 0x182212b4" }, + { "R 0x182212c8" }, + { "R 0x182212dc" }, + { "R 0x182212f0" }, + { "R 0x18221304" }, + { "R 0x18221318" }, + { "R 0x1822132c" }, + { "R 0x18221340" }, + { "R 0x18221354" }, + { "R 0x18221368" }, + { "R 0x1822137c" }, + { "R 0x18221390" }, + { "R 0x182213a4" }, + { "R 0x18221518" }, + { "R 0x1822152c" }, + { "R 0x18221540" }, + { "R 0x18221554" }, + { "R 0x18221568" }, + { "R 0x1822157c" }, + { "R 0x18221590" }, + { "R 0x182215a4" }, + { "R 0x182215b8" }, + { "R 0x182215cc" }, + { "R 0x182215e0" }, + { "R 0x182215f4" }, + { "R 0x18221608" }, + { "R 0x1822161c" }, + { "R 0x18221630" }, + { "R 0x18221644" }, + { "R 0x182217b8" }, + { "R 0x182217cc" }, + { "R 0x182217e0" }, + { "R 0x182217f4" }, + { "R 0x18221808" }, + { "R 0x1822181c" }, + { "R 0x18221830" }, + { "R 0x18221844" }, + { "R 0x18221858" }, + { "R 0x1822186c" }, + { "R 0x18221880" }, + { "R 0x18221894" }, + { "R 0x182218a8" }, + { "R 0x182218bc" }, + { "R 0x182218d0" }, + { "R 0x182218e4" }, + { "R 0x18221a58" }, + { "R 0x18221a6c" }, + { "R 0x18221a80" }, + { "R 0x18221a94" }, + { "R 0x18221aa8" }, + { "R 0x18221abc" }, + { "R 0x18221ad0" }, + { "R 0x18221ae4" }, + { "R 0x18221af8" }, + { "R 0x18221b0c" }, + { "R 0x18221b20" }, + { "R 0x18221b34" }, + { "R 0x18221b48" }, + { "R 0x18221b5c" }, + { "R 0x18221b70" }, + { "R 0x18221b84" }, + { "R 0x18221cf8" }, + { "R 0x18221d0c" }, + { "R 0x18221d20" }, + { "R 0x18221d34" }, + { "R 0x18221d48" }, + { "R 0x18221d5c" }, + { "R 0x18221d70" }, + { "R 0x18221d84" }, + { "R 0x18221d98" }, + { "R 0x18221dac" }, + { "R 0x18221dc0" }, + { "R 0x18221dd4" }, + { "R 0x18221de8" }, + { "R 0x18221dfc" }, + { "R 0x18221e10" }, + { "R 0x18221e24" }, + { "R 0x18221f98" }, + { "R 0x18221fac" }, + { "R 0x18221fc0" }, + { "R 0x18221fd4" }, + { "R 0x18221fe8" }, + { "R 0x18221ffc" }, + { "R 0x18222010" }, + { "R 0x18222024" }, + { "R 0x18222038" }, + { "R 0x1822204c" }, + { "R 0x18222060" }, + { "R 0x18222074" }, + { "R 0x18222088" }, + { "R 0x1822209c" }, + { "R 0x182220b0" }, + { "R 0x182220c4" }, + { "R 0x18000024" }, + { "R 0x18000040" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x180800F8" }, + { "R 0x18080104" }, + { "R 0x1808011C" }, + { "R 0x18080128" }, + { "R 0x90b0280" }, + { "R 0x90b0288" }, + { "R 0x90b028c" }, + { "R 0x90b0290" }, + { "R 0x90b0294" }, + { "R 0x90b0298" }, + { "R 0x90b029c" }, + { "R 0x90b02a0" }, + { "R 0x18321700" }, + { "R 0x18322C18" }, + { "R 0x18323700" }, + { "R 0x18324C18" }, + { "R 0x18325F00" }, + { "R 0x18327418" }, + { "R 0x9236028" }, + { "R 0x923602C" }, + { "R 0x9236030" }, + { "R 0x9236034" }, + { "R 0x9236038" }, + { "R 0x9232100" }, + { "R 0x92360b0" }, + { "R 0x9236044" }, + { "R 0x9236048" }, + { "R 0x923604c" }, + { "R 0x9236050" }, + { "R 0x923e030" }, + { "R 0x923e034" }, + { "R 0x9241000" }, + { "R 0x9248058" }, + { "R 0x924805c" }, + { "R 0x9248060" }, + { "R 0x9248064" }, + { "R 0x9260410" }, + { "R 0x92e0410" }, + { "R 0x9260414" }, + { "R 0x92e0414" }, + { "R 0x9260418" }, + { "R 0x92e0418" }, + { "R 0x9260420" }, + { "R 0x9260424" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92e0420" }, + { "R 0x92e0424" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x9600000" }, + { "R 0x9601000" }, + { "R 0x9602000" }, + { "R 0x9603000" }, + { "R 0x9604000" }, + { "R 0x9605000" }, + { "R 0x9606000" }, + { "R 0x9607000" }, + { "R 0x9608000" }, + { "R 0x9609000" }, + { "R 0x960a000" }, + { "R 0x960b000" }, + { "R 0x960c000" }, + { "R 0x960d000" }, + { "R 0x960e000" }, + { "R 0x960f000" }, + { "R 0x9610000" }, + { "R 0x9611000" }, + { "R 0x9612000" }, + { "R 0x9613000" }, + { "R 0x9614000" }, + { "R 0x9615000" }, + { "R 0x9616000" }, + { "R 0x9617000" }, + { "R 0x9618000" }, + { "R 0x9619000" }, + { "R 0x961a000" }, + { "R 0x961b000" }, + { "R 0x961c000" }, + { "R 0x961d000" }, + { "R 0x961e000" }, + { "R 0x961f000" }, + { "R 0x9600004" }, + { "R 0x9601004" }, + { "R 0x9602004" }, + { "R 0x9603004" }, + { "R 0x9604004" }, + { "R 0x9605004" }, + { "R 0x9606004" }, + { "R 0x9607004" }, + { "R 0x9608004" }, + { "R 0x9609004" }, + { "R 0x960a004" }, + { "R 0x960b004" }, + { "R 0x960c004" }, + { "R 0x960d004" }, + { "R 0x960e004" }, + { "R 0x960f004" }, + { "R 0x9610004" }, + { "R 0x9611004" }, + { "R 0x9612004" }, + { "R 0x9613004" }, + { "R 0x9614004" }, + { "R 0x9615004" }, + { "R 0x9616004" }, + { "R 0x9617004" }, + { "R 0x9618004" }, + { "R 0x9619004" }, + { "R 0x961a004" }, + { "R 0x961b004" }, + { "R 0x961c004" }, + { "R 0x961d004" }, + { "R 0x961e004" }, + { "R 0x961f004" }, + { "R 0x9266418" }, + { "R 0x92e6418" }, + { "R 0x9265804" }, + { "R 0x92e5804" }, + { "R 0x92604b8" }, + { "R 0x92e04b8" }, + { "R 0x0C201244 1" }, + { "R 0x0C202244 1" }, + { "R 0x18100C18 1" }, + { "R 0x18101C18 1" }, + { "R 0x18300000 1" }, + { "R 0x183A3A84 2" }, + { "R 0x18393A84 2" }, + { "R 0x00100000" }, + { "R 0x00100004" }, + { "R 0x00100008" }, + { "R 0x0010000C" }, + { "R 0x00100010" }, + { "R 0x00100014" }, + { "R 0x00100018" }, + { "R 0x0010001C" }, + { "R 0x00100020" }, + { "R 0x00100024" }, + { "R 0x00100028" }, + { "R 0x0010002C" }, + { "R 0x00100030" }, + { "R 0x00100034" }, + { "R 0x00100100" }, + { "R 0x00100104" }, + { "R 0x00100108" }, + { "R 0x0010010C" }, + { "R 0x00101000" }, + { "R 0x00101004" }, + { "R 0x00101008" }, + { "R 0x0010100C" }, + { "R 0x00101010" }, + { "R 0x00101014" }, + { "R 0x00101018" }, + { "R 0x0010101C" }, + { "R 0x00101020" }, + { "R 0x00101024" }, + { "R 0x00101028" }, + { "R 0x0010102C" }, + { "R 0x00101030" }, + { "R 0x00101034" }, + { "R 0x00102000" }, + { "R 0x00102004" }, + { "R 0x00102008" }, + { "R 0x0010200C" }, + { "R 0x00102010" }, + { "R 0x00102014" }, + { "R 0x00102018" }, + { "R 0x0010201C" }, + { "R 0x00102020" }, + { "R 0x00102024" }, + { "R 0x00102028" }, + { "R 0x0010202C" }, + { "R 0x00102030" }, + { "R 0x00102034" }, + { "R 0x00103000" }, + { "R 0x00103004" }, + { "R 0x00103008" }, + { "R 0x0010300C" }, + { "R 0x00103010" }, + { "R 0x00103014" }, + { "R 0x00103018" }, + { "R 0x0010301C" }, + { "R 0x00103020" }, + { "R 0x00103024" }, + { "R 0x00103028" }, + { "R 0x0010302C" }, + { "R 0x00103030" }, + { "R 0x00103034" }, + { "R 0x00113000" }, + { "R 0x00113004" }, + { "R 0x00113008" }, + { "R 0x0011300C" }, + { "R 0x00113010" }, + { "R 0x00113014" }, + { "R 0x00113018" }, + { "R 0x0011301C" }, + { "R 0x00113020" }, + { "R 0x00113024" }, + { "R 0x00113028" }, + { "R 0x0011302C" }, + { "R 0x00113030" }, + { "R 0x00113034" }, + { "R 0x0011A000" }, + { "R 0x0011A004" }, + { "R 0x0011A008" }, + { "R 0x0011A00C" }, + { "R 0x0011A010" }, + { "R 0x0011A014" }, + { "R 0x0011A018" }, + { "R 0x0011A01C" }, + { "R 0x0011A020" }, + { "R 0x0011A024" }, + { "R 0x0011A028" }, + { "R 0x0011A02C" }, + { "R 0x0011A030" }, + { "R 0x0011A034" }, + { "R 0x0011B000" }, + { "R 0x0011B004" }, + { "R 0x0011B008" }, + { "R 0x0011B00C" }, + { "R 0x0011B010" }, + { "R 0x0011B014" }, + { "R 0x0011B018" }, + { "R 0x0011B01C" }, + { "R 0x0011B020" }, + { "R 0x0011B024" }, + { "R 0x0011B028" }, + { "R 0x0011B02C" }, + { "R 0x0011B030" }, + { "R 0x0011B034" }, + { "R 0x00174000" }, + { "R 0x00174004" }, + { "R 0x00174008" }, + { "R 0x0017400C" }, + { "R 0x00174010" }, + { "R 0x00174014" }, + { "R 0x00174018" }, + { "R 0x0017401C" }, + { "R 0x00174020" }, + { "R 0x00174024" }, + { "R 0x00174028" }, + { "R 0x0017402C" }, + { "R 0x00174030" }, + { "R 0x00174034" }, + { "R 0x00176000" }, + { "R 0x00176004" }, + { "R 0x00176008" }, + { "R 0x0017600C" }, + { "R 0x00176010" }, + { "R 0x00176014" }, + { "R 0x00176018" }, + { "R 0x0017601C" }, + { "R 0x00176020" }, + { "R 0x00176024" }, + { "R 0x00176028" }, + { "R 0x0017602C" }, + { "R 0x00176030" }, + { "R 0x00176034" }, + { "R 0x0010401C" }, + { "R 0x00183024" }, + { "R 0x00144168" }, + { "R 0x0011702C" }, + { "R 0x0010904C" }, + { "R 0x00189038" }, + { "R 0x001443E8" }, + { "R 0x001442B8" }, + { "R 0x00105060" }, + { "R 0x00141024" }, + { "R 0x00145038" }, + { "R 0x00109004" }, + { "R 0x00189004" }, + { "R 0x00190004" }, + { "R 0x0C2A0000" }, + { "R 0x0C2A0004" }, + { "R 0x0C2A0008" }, + { "R 0x0C2A000C" }, + { "R 0x0C2A0010" }, + { "R 0x0C2A0014" }, + { "R 0x0C2A0018" }, + { "R 0x0C2A001C" }, + { "R 0x0C2A0020" }, + { "R 0x0C2A0024" }, + { "R 0x0C2A0028" }, + { "R 0x0C2A002C" }, + { "R 0x0C2A0030" }, + { "R 0x0C2A0034" }, + { "R 0x0C2A1000" }, + { "R 0x0C2A1004" }, + { "R 0x0C2A1008" }, + { "R 0x0C2A100C" }, + { "R 0x0C2A1010" }, + { "R 0x0C2A1014" }, + { "R 0x0C2A1018" }, + { "R 0x0C2A101C" }, + { "R 0x0C2A1020" }, + { "R 0x0C2A1024" }, + { "R 0x0C2A1028" }, + { "R 0x0C2A102C" }, + { "R 0x0C2A1030" }, + { "R 0x0C2A2260" }, + { "R 0x0C2A2264" }, + { "R 0x0C2A3008" }, + { "R 0x0C2A300C" }, + { "R 0x0C2A3010" }, + { "R 0x0C2A3014" }, + { "R 0x0C2A3024" }, + { "R 0x0C2A2034" }, + { "R 0x0C2A214C" }, + { "R 0x0C2A2150" }, + { "R 0x0C2A2154" }, + { "R 0x0C2630A0 4" }, + { "R 0x0C2630B0 4" }, + { "R 0x0C2630C0 4" }, + { "R 0x0C2630D0 4" }, + { "R 0x1800005C 1" }, + { "R 0x1801005C 1" }, + { "R 0x1802005C 1" }, + { "R 0x1803005C 1" }, + { "R 0x1804005C 1" }, + { "R 0x1805005C 1" }, + { "R 0x1806005C 1" }, + { "R 0x1807005C 1" }, { "R 0x3d96000" }, { "R 0x3d96004" }, }; From 7c9ef49d17b14e38b6c4889bf5714abb670d19ff Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 21:26:53 +0800 Subject: [PATCH 0019/1058] QCLINUX: qcom-dcc: use late_initcall and build as built-in for boot debug The DCC device stub driver was registered with module_init(), which runs during the initcall sequence before late_initcall(). The DCC hardware depends on resources that are not yet available at that point, causing the driver to fail silently during early boot. Switch to late_initcall() so the driver initialises after all subsystem dependencies are ready. Remove the module_exit() registration since the driver is now built-in only. Update qcom_debug.config to build CONFIG_QCOM_DCC and CONFIG_QCOM_DCC_DEV as built-in (=y) instead of loadable modules (=m) to match the late_initcall() requirement and allow early boot debugging. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 4 ++-- drivers/misc/qcom-dcc-dev.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 48ae2fb9737ac..0419414d6c51b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ -CONFIG_QCOM_DCC=m -CONFIG_QCOM_DCC_DEV=m +CONFIG_QCOM_DCC=y +CONFIG_QCOM_DCC_DEV=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 7656e8e90aa1c..4d0c9c9526da3 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -978,7 +978,6 @@ static void __exit dcc_dev_exit(void) platform_device_unregister(dcc_pdev); } -module_init(dcc_dev_init); -module_exit(dcc_dev_exit); +late_initcall(dcc_dev_init); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver, device stub"); From a8695a4a179e6003a346cf0ec16978ab6f689a6e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 21:27:10 +0800 Subject: [PATCH 0020/1058] QCLINUX: memory-dump: use late_initcall and build as built-in for boot debug The memory dump device stub driver was registered with module_init(), which runs before late_initcall(). The memory dump subsystem depends on resources that are not yet available at that point, causing the driver to fail silently during early boot. Switch to late_initcall() so the driver initialises after all subsystem dependencies are ready. Remove the module_exit() registration since the driver is now built-in only. Update qcom_debug.config to build CONFIG_QCOM_MEMORY_DUMP_DEV as built-in (=y) instead of a loadable module (=m) to match the late_initcall() requirement and allow early boot debugging. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 2 +- drivers/firmware/qcom/memory_dump_dev.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 0419414d6c51b..1399972795b68 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ CONFIG_QCOM_DCC=y CONFIG_QCOM_DCC_DEV=y CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_QCOM_MEMORY_DUMP_DEV=m +CONFIG_QCOM_MEMORY_DUMP_DEV=y diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0c0cb06462cc5..0845aa152dc2f 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -513,7 +513,6 @@ static void __exit mem_dump_dev_exit(void) platform_device_unregister(mem_dump_pdev); } -module_init(mem_dump_dev_init); -module_exit(mem_dump_dev_exit); +late_initcall(mem_dump_dev_init); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Qualcomm Technologies Inc. Memory Dump driver V2, device stub"); From e4c2182d6741e7d5ab987e32ca7f3b8ef5befed9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 11:34:26 +0800 Subject: [PATCH 0021/1058] QCLINUX: qcom-dcc: add lemans register list and move config to header Add the full DCC register capture list for the Lemans platform derived from debug_config_qcs9100.sh. The registers cover LPM, TSENS, PLL, LIMITS, and DDR subsystems, all configured on linked list 6 to match the runtime script (LLNUM=6 in configure_dcc()). Consecutive single-word reads are merged into burst entries (e.g. "R addr N") to keep the array compact; the kernel driver merges them identically via dcc_config_add(). Estimated SRAM usage is ~19 KB, within the 24 KB (0x6000) budget for the Lemans DCC RAM. Move the lemans DCC configuration (entries array, link config, dcc config, and pdata) into a dedicated header qcom-dcc-lemans-config.h to avoid bloating qcom-dcc-dev.c with the large register table. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 29 +- drivers/misc/qcom-dcc-lemans-config.h | 1630 +++++++++++++++++++++++++ 2 files changed, 1631 insertions(+), 28 deletions(-) create mode 100644 drivers/misc/qcom-dcc-lemans-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 4d0c9c9526da3..d3dcda2d3e5fc 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -7,6 +7,7 @@ #include #include #include "qcom-dcc.h" +#include "qcom-dcc-lemans-config.h" #define DEV_NAME "qcom-dcc" @@ -793,34 +794,6 @@ static const struct dcc_pdata talos_pdata = { .config = &talos_config, }; -static const struct dcc_register_entry lemans_dcc_entries[] = { - { "R 0x610110 1" }, - { "R 0x9050008 1" }, -}; - -static const struct dcc_link_config lemans_link_configs[] = { - { - .link_list = 6, - .entries = lemans_dcc_entries, - .num_entries = ARRAY_SIZE(lemans_dcc_entries), - }, -}; - -static const struct dcc_config lemans_config = { - .lists = lemans_link_configs, - .num_lists = ARRAY_SIZE(lemans_link_configs), -}; - -static const struct dcc_pdata lemans_pdata = { - .base = 0x040ff000, - .size = 0x00001000, - .ram_base = 0x040b8800, - .ram_size = 0x00006000, - .dcc_offset = 0x38800, - .map_ver = 0x3, - .config = &lemans_config, -}; - static const struct dcc_pdata kodiak_pdata = { .base = 0x0117f000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-lemans-config.h b/drivers/misc/qcom-dcc-lemans-config.h new file mode 100644 index 0000000000000..01327a67eac91 --- /dev/null +++ b/drivers/misc/qcom-dcc-lemans-config.h @@ -0,0 +1,1630 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_LEMANS_CONFIG_H +#define _QCOM_DCC_LEMANS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry lemans_dcc_entries[] = { + /* lpm */ + { "R 0x18000040" }, + { "R 0x18000024" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x18090024" }, + { "R 0x18090040" }, + { "R 0x18090104" }, + { "R 0x180900f8" }, + { "R 0x180800f4" }, + { "R 0x18080104" }, + { "R 0x180800f8" }, + { "R 0x180900f4" }, + { "R 0x18210404 2" }, + { "R 0xb201024" }, + { "R 0xb201020" }, + { "R 0xb211020" }, + { "R 0xb221020" }, + { "R 0xb232020" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + { "R 0xc224004" }, + { "R 0xc251014" }, + { "R 0xc2510e0" }, + { "R 0xc2510ec" }, + { "R 0xc2510a0 16" }, + { "R 0xc2510e8" }, + { "R 0xc25113c" }, + { "R 0xc225004" }, + { "R 0xc252014" }, + { "R 0xc2520e0" }, + { "R 0xc2520ec" }, + { "R 0xc2520a0 16" }, + { "R 0xc2520e8" }, + { "R 0xc25213c" }, + /* pll */ + { "R 0x182b0000 12" }, + { "R 0x182b003c" }, + { "R 0x182b4000 12" }, + { "R 0x182b403c" }, + { "R 0x18280044" }, + { "R 0x1828004c" }, + { "R 0x18280060" }, + { "R 0x18284044" }, + { "R 0x1828404c" }, + { "R 0x18284060" }, + { "R 0x182b2000 12" }, + { "R 0x182b203c" }, + { "R 0x182b6000 12" }, + { "R 0x182b603c" }, + { "R 0x18282044" }, + { "R 0x1828204c" }, + { "R 0x18282060" }, + { "R 0x18286044" }, + { "R 0x1828604c" }, + { "R 0x18286060" }, + /* limits */ + { "R 0xec80010" }, + { "R 0xec81000" }, + { "R 0xec81010 64" }, + { "R 0x18378220 2" }, + { "R 0x183782a0 2" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d90 12" }, + { "R 0x18379010 10" }, + { "R 0x18379090 10" }, + { "R 0x18379a90 8" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d90 12" }, + { "R 0x18371010 10" }, + { "R 0x18371090 10" }, + { "R 0x18371a90 8" }, + { "R 0x26310220 3" }, + { "R 0x263102a0 3" }, + { "R 0x263104a0 6" }, + { "R 0x26310520" }, + { "R 0x26310588" }, + { "R 0x26310d90 8" }, + { "R 0x26311010 6" }, + { "R 0x26311090 6" }, + { "R 0x26311a90 3" }, + { "R 0x2a310220 3" }, + { "R 0x2a3102a0 3" }, + { "R 0x2a3104a0 6" }, + { "R 0x2a310520" }, + { "R 0x2a310588" }, + { "R 0x2a310d90 8" }, + { "R 0x2a311010 6" }, + { "R 0x2a311090 6" }, + { "R 0x2a311a90 3" }, + /* ddr */ + { "R 0x610110" }, + { "R 0x9050008" }, + { "R 0x905001c" }, + { "R 0x9050030" }, + { "R 0x9050050" }, + { "R 0x9050070" }, + { "R 0x9050948" }, + { "R 0x905104c" }, + { "R 0x9050078" }, + { "R 0x9050114" }, + { "R 0x90a0008 2" }, + { "R 0x90a0080" }, + { "R 0x90a1008 2" }, + { "R 0x90a80e4 2" }, + { "R 0x90a816c 2" }, + { "R 0x90a80f8" }, + { "R 0x90a8180 2" }, + { "R 0x90a81a0 2" }, + { "R 0x90a81c0 2" }, + { "R 0x90a81e4" }, + { "R 0x90a81f4" }, + { "R 0x90a8204" }, + { "R 0x90a8218" }, + { "R 0x90a8228" }, + { "R 0x90a8264 2" }, + { "R 0x90a8270" }, + { "R 0x90a80fc 4" }, + { "R 0x90a8148 2" }, + { "R 0x90a8158 2" }, + { "R 0x90a8190 2" }, + { "R 0x90a81b0 2" }, + { "R 0x90a81d0 2" }, + { "R 0x90a84f4" }, + { "R 0x90a8138" }, + { "R 0x90a8150" }, + { "R 0x90a8160" }, + { "R 0x90a8198" }, + { "R 0x90a81b8" }, + { "R 0x90a81d8" }, + { "R 0x90a8280" }, + { "R 0x90a819c" }, + { "R 0x90a81bc" }, + { "R 0x90a81dc" }, + { "R 0x90a821c" }, + { "R 0x90a822c" }, + { "R 0x90a84f8" }, + { "R 0x90a9204" }, + { "R 0x90a880c" }, + { "R 0x90a8834" }, + { "R 0x90a8840 2" }, + { "R 0x90a8850 2" }, + { "R 0x90a8860 3" }, + { "R 0x90a8878" }, + { "R 0x90a8884" }, + { "R 0x90a9260" }, + { "R 0x90a8900" }, + { "R 0x90a9134 2" }, + { "R 0x90a8880 3" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x90e5008" }, + { "R 0x90e5010 3" }, + { "R 0x9080024" }, + { "R 0x908002c" }, + { "R 0x9080034" }, + { "R 0x908003c" }, + { "R 0x9080044" }, + { "R 0x908004c" }, + { "R 0x9080054 3" }, + { "R 0x90800b8 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800ec" }, + { "R 0x90800f8" }, + { "R 0x9080104 2" }, + { "R 0x9080114" }, + { "R 0x9080144" }, + { "R 0x908014c" }, + { "R 0x9080168" }, + { "R 0x9080174" }, + { "R 0x90801ac" }, + { "R 0x90801b4" }, + { "R 0x90801bc" }, + { "R 0x90801c4" }, + { "R 0x90801cc" }, + { "R 0x90801d4" }, + { "R 0x90801dc" }, + { "R 0x90801e4" }, + { "R 0x90801ec" }, + { "R 0x90801f4 2" }, + { "R 0x90ba000" }, + { "R 0x90ba050" }, + { "R 0x90ba280" }, + { "R 0x90ba288" }, + { "R 0x9280610 4" }, + { "R 0x9280680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9480610 4" }, + { "R 0x9480680 4" }, + { "R 0x9580610 4" }, + { "R 0x9580680 4" }, + { "R 0x9680610 4" }, + { "R 0x9680680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9100008" }, + { "R 0x9100010" }, + { "R 0x9100408" }, + { "R 0x9100410" }, + { "R 0x9100808" }, + { "R 0x9100810" }, + { "R 0x9100c08" }, + { "R 0x9100c10" }, + { "R 0x9101008" }, + { "R 0x9101010" }, + { "R 0x9101408" }, + { "R 0x9101410" }, + { "R 0x9101808" }, + { "R 0x9101810" }, + { "R 0x9101c08" }, + { "R 0x9101c10" }, + { "R 0x9102008" }, + { "R 0x9102010" }, + { "R 0x9102408" }, + { "R 0x9102410" }, + { "R 0x9102808" }, + { "R 0x9102810" }, + { "R 0x9102c08" }, + { "R 0x9102c10" }, + { "R 0x9103000 3" }, + { "R 0x9103010 3" }, + { "R 0x9103080 3" }, + { "R 0x9103090 3" }, + { "R 0x9104008" }, + { "R 0x9105008" }, + { "R 0x9106008" }, + { "R 0x9107008" }, + { "R 0x9108008" }, + { "R 0x9108808" }, + { "R 0x9109008" }, + { "R 0x9109808" }, + { "R 0x9122008" }, + { "R 0x9122408" }, + { "R 0x9122808" }, + { "R 0x9122c08" }, + { "R 0x9123008" }, + { "R 0x9123408" }, + { "R 0x9123808" }, + { "R 0x9123c08" }, + { "R 0x9124008" }, + { "R 0x9124408" }, + { "R 0x9124808" }, + { "R 0x9124c08" }, + { "R 0x9138008" }, + { "R 0x9138088" }, + { "R 0x9138108" }, + { "R 0x9138188" }, + { "R 0x9138208" }, + { "R 0x9138288" }, + { "R 0x9138308" }, + { "R 0x9138388" }, + { "R 0x9138408" }, + { "R 0x9138488" }, + { "R 0x9138508" }, + { "R 0x9138588" }, + { "R 0x9138608" }, + { "R 0x9138688" }, + { "R 0x9140000 5" }, + { "R 0x9140018" }, + { "R 0x9140020 3" }, + { "R 0x9140030 3" }, + { "R 0x9140040 3" }, + { "R 0x9140400 5" }, + { "R 0x9140418" }, + { "R 0x9140420 3" }, + { "R 0x9140430 3" }, + { "R 0x9140440 3" }, + { "R 0x9140800 5" }, + { "R 0x9140818" }, + { "R 0x9140820 3" }, + { "R 0x9140830 3" }, + { "R 0x9140840 3" }, + { "R 0x9140c00 5" }, + { "R 0x9140c18" }, + { "R 0x9140c20 3" }, + { "R 0x9140c30 3" }, + { "R 0x9140c40 3" }, + { "R 0x9141000 5" }, + { "R 0x9141018" }, + { "R 0x9141020 3" }, + { "R 0x9141030 3" }, + { "R 0x9141040 3" }, + { "R 0x9141400 5" }, + { "R 0x9141418" }, + { "R 0x9141420 3" }, + { "R 0x9141430 3" }, + { "R 0x9141440 3" }, + { "R 0x9141800 3" }, + { "R 0x9141810 3" }, + { "R 0x9141880 3" }, + { "R 0x9141890 3" }, + { "R 0x9142008" }, + { "R 0x9143008" }, + { "R 0x9144008" }, + { "R 0x9145008" }, + { "R 0x9146008" }, + { "R 0x9147008" }, + { "R 0x9148008" }, + { "R 0x9149008" }, + { "R 0x914a008" }, + { "R 0x914b008" }, + { "R 0x914c008" }, + { "R 0x914d008" }, + { "R 0x914e008" }, + { "R 0x914e208" }, + { "R 0x914e408" }, + { "R 0x914e608" }, + { "R 0x914e808" }, + { "R 0x914ea08" }, + { "R 0x914f008" }, + { "R 0x914f808" }, + { "R 0x9150008" }, + { "R 0x9150808" }, + { "R 0x9151008" }, + { "R 0x9151808" }, + { "R 0x9152008" }, + { "R 0x9153008" }, + { "R 0x9154008" }, + { "R 0x9155008" }, + { "R 0x9156008" }, + { "R 0x9157008" }, + { "R 0x9163008" }, + { "R 0x9163010" }, + { "R 0x9165008" }, + { "R 0x9165010" }, + { "R 0x9167008" }, + { "R 0x9167010" }, + { "R 0x9169008" }, + { "R 0x9169010" }, + { "R 0x916b008" }, + { "R 0x916b010" }, + { "R 0x916d008" }, + { "R 0x916d010" }, + { "R 0x9170000 3" }, + { "R 0x9170010" }, + { "R 0x9170018" }, + { "R 0x9170020 6" }, + { "R 0x9170400 3" }, + { "R 0x9170410" }, + { "R 0x9170418" }, + { "R 0x9170420 6" }, + { "R 0x9170800 3" }, + { "R 0x9170810" }, + { "R 0x9170818" }, + { "R 0x9170820 6" }, + { "R 0x9170c00 3" }, + { "R 0x9170c10" }, + { "R 0x9170c18" }, + { "R 0x9170c20 6" }, + { "R 0x9171000 3" }, + { "R 0x9171010" }, + { "R 0x9171018" }, + { "R 0x9171020 6" }, + { "R 0x9171400 3" }, + { "R 0x9171410" }, + { "R 0x9171418" }, + { "R 0x9171420 6" }, + { "R 0x9178008" }, + { "R 0x9178088" }, + { "R 0x9178108" }, + { "R 0x9178188" }, + { "R 0x9178208" }, + { "R 0x9178288" }, + { "R 0x9178308" }, + { "R 0x9178388" }, + { "R 0x9178408" }, + { "R 0x9178488" }, + { "R 0x9178508" }, + { "R 0x9180000 5" }, + { "R 0x9180018" }, + { "R 0x9180020 3" }, + { "R 0x9180030 3" }, + { "R 0x9180040 3" }, + { "R 0x9180400 5" }, + { "R 0x9180418" }, + { "R 0x9180420 3" }, + { "R 0x9180430 3" }, + { "R 0x9180440 3" }, + { "R 0x9180800 3" }, + { "R 0x9180810 3" }, + { "R 0x9180880 3" }, + { "R 0x9180890 3" }, + { "R 0x9180900 3" }, + { "R 0x9180910 3" }, + { "R 0x9180a08" }, + { "R 0x9181008" }, + { "R 0x9181808" }, + { "R 0x9182208" }, + { "R 0x9182408" }, + { "R 0x9182608" }, + { "R 0x9182808" }, + { "R 0x9182a08" }, + { "R 0x9182c08" }, + { "R 0x9182e08" }, + { "R 0x9183008" }, + { "R 0x9183808" }, + { "R 0x9184008" }, + { "R 0x9185008" }, + { "R 0x9186008" }, + { "R 0x9187008" }, + { "R 0x9188008" }, + { "R 0x9189008" }, + { "R 0x918a008" }, + { "R 0x918b008" }, + { "R 0x9190000 3" }, + { "R 0x9190010" }, + { "R 0x9190018" }, + { "R 0x9190020 6" }, + { "R 0x9190400 3" }, + { "R 0x9190410" }, + { "R 0x9190418" }, + { "R 0x9190420 6" }, + { "R 0x9197008" }, + { "R 0x9197088" }, + { "R 0x9198008" }, + { "R 0x9198088" }, + { "R 0x9198108" }, + { "R 0x9198188" }, + { "R 0x9198208" }, + { "R 0x9198288" }, + { "R 0x9198308" }, + { "R 0x9198388" }, + { "R 0x9198408" }, + { "R 0x9198508" }, + { "R 0x9198588" }, + { "R 0x9198608" }, + { "R 0x9198688" }, + { "R 0x9198708" }, + { "R 0x9198788" }, + { "R 0x9198808" }, + { "R 0x9198888" }, + { "R 0x9198908" }, + { "R 0x9198988" }, + { "R 0x9198a08" }, + { "R 0x9198a88" }, + { "R 0x9198b08" }, + { "R 0x9198b88" }, + { "R 0x9198c08" }, + { "R 0x9198e40" }, + { "R 0x9198e48" }, + { "R 0x91a0008" }, + { "R 0x91a1008" }, + { "R 0x91a2008" }, + { "R 0x91a6040" }, + { "R 0x91a6048" }, + { "R 0x91a8100 4" }, + { "R 0x91ab100" }, + { "R 0x91ac040" }, + { "R 0x91ac048" }, + { "R 0x91ad008" }, + { "R 0x91ad010" }, + { "R 0x91ae008" }, + { "R 0x91ae010" }, + { "R 0x91af008" }, + { "R 0x91af010" }, + { "R 0x91b0008" }, + { "R 0x91b0010" }, + { "R 0x91b1008" }, + { "R 0x91b1010" }, + { "R 0x91b2008" }, + { "R 0x91b2010" }, + { "R 0x91b3008" }, + { "R 0x91b3010" }, + { "R 0x91b4008" }, + { "R 0x91b4010" }, + { "R 0x91b5008" }, + { "R 0x91b5010" }, + { "R 0x91b6008" }, + { "R 0x91b6010" }, + { "R 0x91b7008" }, + { "R 0x91b7010" }, + { "R 0x91b8008" }, + { "R 0x91b8010" }, + { "R 0x91b9008" }, + { "R 0x91b9010" }, + { "R 0x91ba008" }, + { "R 0x91ba010" }, + { "R 0x91c0008" }, + { "R 0x91c0208" }, + { "R 0x91c0408" }, + { "R 0x91c0608" }, + { "R 0x91c0808" }, + { "R 0x91c0a08" }, + { "R 0x91c0c08" }, + { "R 0x91c0e08" }, + { "R 0x91c1008" }, + { "R 0x91c1208" }, + { "R 0x91c1408" }, + { "R 0x91c1608" }, + { "R 0x91c1808" }, + { "R 0x91c1a08" }, + { "R 0x91c1c08" }, + { "R 0x91c1e08" }, + { "R 0x91d8008" }, + { "R 0x91d8088" }, + { "R 0x91d8108" }, + { "R 0x91d8188" }, + { "R 0x91d8208" }, + { "R 0x91d8288" }, + { "R 0x91d8308" }, + { "R 0x91d8388" }, + { "R 0x91d8408" }, + { "R 0x91d8488" }, + { "R 0x91d8508" }, + { "R 0x91d8588" }, + { "R 0x91d8608" }, + { "R 0x91d8688" }, + { "R 0x91d8708" }, + { "R 0x91d8788" }, + { "R 0x91e1008" }, + { "R 0x91e1088" }, + { "R 0x91e1108" }, + { "R 0x91e3008" }, + { "R 0x91e3010" }, + { "R 0x91e4008" }, + { "R 0x91e4010" }, + { "R 0x91e5008" }, + { "R 0x91e5010" }, + { "R 0x91e6008" }, + { "R 0x91e6010" }, + { "R 0x91e7008" }, + { "R 0x91e7010" }, + { "R 0x91e8008" }, + { "R 0x91e8010" }, + { "R 0x91e9008" }, + { "R 0x91e9010" }, + { "R 0x91ea008" }, + { "R 0x91ea010" }, + { "R 0x91eb008" }, + { "R 0x91eb010" }, + { "R 0x91ec008" }, + { "R 0x91ec010" }, + { "R 0x91ed008" }, + { "R 0x91ed010" }, + { "R 0x91ee008" }, + { "R 0x91ee010" }, + { "R 0x91ef008" }, + { "R 0x91ef010" }, + { "R 0x91f0008" }, + { "R 0x91f0010" }, + { "R 0x91f1008" }, + { "R 0x91f1010" }, + { "R 0x91f2008" }, + { "R 0x91f2010" }, + { "R 0x91f3008" }, + { "R 0x91f3010" }, + { "R 0x91f4008" }, + { "R 0x91f4010" }, + { "R 0x91f5008" }, + { "R 0x91f5010" }, + { "R 0x91f6008" }, + { "R 0x91f6010" }, + { "R 0x9220344 9" }, + { "R 0x9220370 7" }, + { "R 0x9220480" }, + { "R 0x9222400 26" }, + { "R 0x9222470 5" }, + { "R 0x922320c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 4" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x922358c" }, + { "R 0x9234010" }, + { "R 0x923801c 8" }, + { "R 0x9238050" }, + { "R 0x9238100 7" }, + { "R 0x923c004" }, + { "R 0x923c014" }, + { "R 0x923c020" }, + { "R 0x923c030" }, + { "R 0x923c05c 3" }, + { "R 0x923c074" }, + { "R 0x923c088" }, + { "R 0x923c0a0" }, + { "R 0x923c0b0" }, + { "R 0x923c0c0" }, + { "R 0x923c0d0" }, + { "R 0x923c0e0" }, + { "R 0x923c0f0" }, + { "R 0x923c100" }, + { "R 0x923d064" }, + { "R 0x9240008 6" }, + { "R 0x9240028" }, + { "R 0x924203c 6" }, + { "R 0x9242058 7" }, + { "R 0x924208c" }, + { "R 0x92420b0" }, + { "R 0x92420b8 3" }, + { "R 0x92420f4" }, + { "R 0x92420fc 7" }, + { "R 0x9242324 14" }, + { "R 0x9242410" }, + { "R 0x92430a8" }, + { "R 0x9248004 7" }, + { "R 0x9248024" }, + { "R 0x9248040" }, + { "R 0x9248048" }, + { "R 0x9249064" }, + { "R 0x924c000" }, + { "R 0x924c030 3" }, + { "R 0x924c040 3" }, + { "R 0x924c054 2" }, + { "R 0x924c078" }, + { "R 0x924c108" }, + { "R 0x924c110" }, + { "R 0x9250020" }, + { "R 0x9251054" }, + { "R 0x9252014 3" }, + { "R 0x9252028 17" }, + { "R 0x9252070 8" }, + { "R 0x9252098" }, + { "R 0x92520a0" }, + { "R 0x92520b4" }, + { "R 0x92520c0 4" }, + { "R 0x92520f4 10" }, + { "R 0x9252120 12" }, + { "R 0x925802c" }, + { "R 0x925809c 2" }, + { "R 0x92580a8 3" }, + { "R 0x92580b8" }, + { "R 0x92580c0 7" }, + { "R 0x92580e0" }, + { "R 0x92580e8" }, + { "R 0x92580f0" }, + { "R 0x92580f8" }, + { "R 0x9258100" }, + { "R 0x9258108" }, + { "R 0x9258110" }, + { "R 0x9258118" }, + { "R 0x9258120" }, + { "R 0x9258128" }, + { "R 0x9258210 3" }, + { "R 0x9259010" }, + { "R 0x9259070" }, + { "R 0x925b004" }, + { "R 0x926004c 10" }, + { "R 0x9260078" }, + { "R 0x926020c" }, + { "R 0x9260214" }, + { "R 0x9261084" }, + { "R 0x9262020" }, + { "R 0x9263020" }, + { "R 0x9264020" }, + { "R 0x9265020" }, + { "R 0x9320344 9" }, + { "R 0x9320370 7" }, + { "R 0x9320480" }, + { "R 0x9322400 26" }, + { "R 0x9322470 5" }, + { "R 0x932320c" }, + { "R 0x9323214 2" }, + { "R 0x9323220 4" }, + { "R 0x9323308" }, + { "R 0x9323318" }, + { "R 0x932358c" }, + { "R 0x9334010" }, + { "R 0x933801c 8" }, + { "R 0x9338050" }, + { "R 0x9338100 7" }, + { "R 0x933c004" }, + { "R 0x933c014" }, + { "R 0x933c020" }, + { "R 0x933c030" }, + { "R 0x933c05c 3" }, + { "R 0x933c074" }, + { "R 0x933c088" }, + { "R 0x933c0a0" }, + { "R 0x933c0b0" }, + { "R 0x933c0c0" }, + { "R 0x933c0d0" }, + { "R 0x933c0e0" }, + { "R 0x933c0f0" }, + { "R 0x933c100" }, + { "R 0x933d064" }, + { "R 0x9340008 6" }, + { "R 0x9340028" }, + { "R 0x934203c 6" }, + { "R 0x9342058 7" }, + { "R 0x934208c" }, + { "R 0x93420b0" }, + { "R 0x93420b8 3" }, + { "R 0x93420f4" }, + { "R 0x93420fc 7" }, + { "R 0x9342324 14" }, + { "R 0x9342410" }, + { "R 0x93430a8" }, + { "R 0x9348004 7" }, + { "R 0x9348024" }, + { "R 0x9348040" }, + { "R 0x9348048" }, + { "R 0x9349064" }, + { "R 0x934c000" }, + { "R 0x934c030 3" }, + { "R 0x934c040 3" }, + { "R 0x934c054 2" }, + { "R 0x934c078" }, + { "R 0x934c108" }, + { "R 0x934c110" }, + { "R 0x9350020" }, + { "R 0x9351054" }, + { "R 0x9352014 3" }, + { "R 0x9352028 17" }, + { "R 0x9352070 8" }, + { "R 0x9352098" }, + { "R 0x93520a0" }, + { "R 0x93520b4" }, + { "R 0x93520c0 4" }, + { "R 0x93520f4 10" }, + { "R 0x9352120 12" }, + { "R 0x935802c" }, + { "R 0x935809c 2" }, + { "R 0x93580a8 3" }, + { "R 0x93580b8" }, + { "R 0x93580c0 7" }, + { "R 0x93580e0" }, + { "R 0x93580e8" }, + { "R 0x93580f0" }, + { "R 0x93580f8" }, + { "R 0x9358100" }, + { "R 0x9358108" }, + { "R 0x9358110" }, + { "R 0x9358118" }, + { "R 0x9358120" }, + { "R 0x9358128" }, + { "R 0x9358210 3" }, + { "R 0x9359010" }, + { "R 0x9359070" }, + { "R 0x935b004" }, + { "R 0x936004c 10" }, + { "R 0x9360078" }, + { "R 0x936020c" }, + { "R 0x9360214" }, + { "R 0x9361084" }, + { "R 0x9362020" }, + { "R 0x9363020" }, + { "R 0x9364020" }, + { "R 0x9365020" }, + { "R 0x9420344 9" }, + { "R 0x9420370 7" }, + { "R 0x9420480" }, + { "R 0x9422400 26" }, + { "R 0x9422470 5" }, + { "R 0x942320c" }, + { "R 0x9423214 2" }, + { "R 0x9423220 4" }, + { "R 0x9423308" }, + { "R 0x9423318" }, + { "R 0x942358c" }, + { "R 0x9434010" }, + { "R 0x943801c 8" }, + { "R 0x9438050" }, + { "R 0x9438100 7" }, + { "R 0x943c004" }, + { "R 0x943c014" }, + { "R 0x943c020" }, + { "R 0x943c030" }, + { "R 0x943c05c 3" }, + { "R 0x943c074" }, + { "R 0x943c088" }, + { "R 0x943c0a0" }, + { "R 0x943c0b0" }, + { "R 0x943c0c0" }, + { "R 0x943c0d0" }, + { "R 0x943c0e0" }, + { "R 0x943c0f0" }, + { "R 0x943c100" }, + { "R 0x943d064" }, + { "R 0x9440008 6" }, + { "R 0x9440028" }, + { "R 0x944203c 6" }, + { "R 0x9442058 7" }, + { "R 0x944208c" }, + { "R 0x94420b0" }, + { "R 0x94420b8 3" }, + { "R 0x94420f4" }, + { "R 0x94420fc 7" }, + { "R 0x9442324 14" }, + { "R 0x9442410" }, + { "R 0x94430a8" }, + { "R 0x9448004 7" }, + { "R 0x9448024" }, + { "R 0x9448040" }, + { "R 0x9448048" }, + { "R 0x9449064" }, + { "R 0x944c000" }, + { "R 0x944c030 3" }, + { "R 0x944c040 3" }, + { "R 0x944c054 2" }, + { "R 0x944c078" }, + { "R 0x944c108" }, + { "R 0x944c110" }, + { "R 0x9450020" }, + { "R 0x9451054" }, + { "R 0x9452014 3" }, + { "R 0x9452028 17" }, + { "R 0x9452070 8" }, + { "R 0x9452098" }, + { "R 0x94520a0" }, + { "R 0x94520b4" }, + { "R 0x94520c0 4" }, + { "R 0x94520f4 10" }, + { "R 0x9452120 12" }, + { "R 0x945802c" }, + { "R 0x945809c 2" }, + { "R 0x94580a8 3" }, + { "R 0x94580b8" }, + { "R 0x94580c0 7" }, + { "R 0x94580e0" }, + { "R 0x94580e8" }, + { "R 0x94580f0" }, + { "R 0x94580f8" }, + { "R 0x9458100" }, + { "R 0x9458108" }, + { "R 0x9458110" }, + { "R 0x9458118" }, + { "R 0x9458120" }, + { "R 0x9458128" }, + { "R 0x9458210 3" }, + { "R 0x9459010" }, + { "R 0x9459070" }, + { "R 0x945b004" }, + { "R 0x946004c 10" }, + { "R 0x9460078" }, + { "R 0x946020c" }, + { "R 0x9460214" }, + { "R 0x9461084" }, + { "R 0x9462020" }, + { "R 0x9463020" }, + { "R 0x9464020" }, + { "R 0x9465020" }, + { "R 0x9520344 9" }, + { "R 0x9520370 7" }, + { "R 0x9520480" }, + { "R 0x9522400 26" }, + { "R 0x9522470 5" }, + { "R 0x952320c" }, + { "R 0x9523214 2" }, + { "R 0x9523220 4" }, + { "R 0x9523308" }, + { "R 0x9523318" }, + { "R 0x952358c" }, + { "R 0x9534010" }, + { "R 0x953801c 8" }, + { "R 0x9538050" }, + { "R 0x9538100 7" }, + { "R 0x953c004" }, + { "R 0x953c014" }, + { "R 0x953c020" }, + { "R 0x953c030" }, + { "R 0x953c05c 3" }, + { "R 0x953c074" }, + { "R 0x953c088" }, + { "R 0x953c0a0" }, + { "R 0x953c0b0" }, + { "R 0x953c0c0" }, + { "R 0x953c0d0" }, + { "R 0x953c0e0" }, + { "R 0x953c0f0" }, + { "R 0x953c100" }, + { "R 0x953d064" }, + { "R 0x9540008 6" }, + { "R 0x9540028" }, + { "R 0x954203c 6" }, + { "R 0x9542058 7" }, + { "R 0x954208c" }, + { "R 0x95420b0" }, + { "R 0x95420b8 3" }, + { "R 0x95420f4" }, + { "R 0x95420fc 7" }, + { "R 0x9542324 14" }, + { "R 0x9542410" }, + { "R 0x95430a8" }, + { "R 0x9548004 7" }, + { "R 0x9548024" }, + { "R 0x9548040" }, + { "R 0x9548048" }, + { "R 0x9549064" }, + { "R 0x954c000" }, + { "R 0x954c030 3" }, + { "R 0x954c040 3" }, + { "R 0x954c054 2" }, + { "R 0x954c078" }, + { "R 0x954c108" }, + { "R 0x954c110" }, + { "R 0x9550020" }, + { "R 0x9551054" }, + { "R 0x9552014 3" }, + { "R 0x9552028 17" }, + { "R 0x9552070 8" }, + { "R 0x9552098" }, + { "R 0x95520a0" }, + { "R 0x95520b4" }, + { "R 0x95520c0 4" }, + { "R 0x95520f4 10" }, + { "R 0x9552120 12" }, + { "R 0x955802c" }, + { "R 0x955809c 2" }, + { "R 0x95580a8 3" }, + { "R 0x95580b8" }, + { "R 0x95580c0 7" }, + { "R 0x95580e0" }, + { "R 0x95580e8" }, + { "R 0x95580f0" }, + { "R 0x95580f8" }, + { "R 0x9558100" }, + { "R 0x9558108" }, + { "R 0x9558110" }, + { "R 0x9558118" }, + { "R 0x9558120" }, + { "R 0x9558128" }, + { "R 0x9558210 3" }, + { "R 0x9559010" }, + { "R 0x9559070" }, + { "R 0x955b004" }, + { "R 0x956004c 10" }, + { "R 0x9560078" }, + { "R 0x956020c" }, + { "R 0x9560214" }, + { "R 0x9561084" }, + { "R 0x9562020" }, + { "R 0x9563020" }, + { "R 0x9564020" }, + { "R 0x9565020" }, + { "R 0x9620344 9" }, + { "R 0x9620370 7" }, + { "R 0x9620480" }, + { "R 0x9622400 26" }, + { "R 0x9622470 5" }, + { "R 0x962320c" }, + { "R 0x9623214 2" }, + { "R 0x9623220 4" }, + { "R 0x9623308" }, + { "R 0x9623318" }, + { "R 0x962358c" }, + { "R 0x9634010" }, + { "R 0x963801c 8" }, + { "R 0x9638050" }, + { "R 0x9638100 7" }, + { "R 0x963c004" }, + { "R 0x963c014" }, + { "R 0x963c020" }, + { "R 0x963c030" }, + { "R 0x963c05c 3" }, + { "R 0x963c074" }, + { "R 0x963c088" }, + { "R 0x963c0a0" }, + { "R 0x963c0b0" }, + { "R 0x963c0c0" }, + { "R 0x963c0d0" }, + { "R 0x963c0e0" }, + { "R 0x963c0f0" }, + { "R 0x963c100" }, + { "R 0x963d064" }, + { "R 0x9640008 6" }, + { "R 0x9640028" }, + { "R 0x964203c 6" }, + { "R 0x9642058 7" }, + { "R 0x964208c" }, + { "R 0x96420b0" }, + { "R 0x96420b8 3" }, + { "R 0x96420f4" }, + { "R 0x96420fc 7" }, + { "R 0x9642324 14" }, + { "R 0x9642410" }, + { "R 0x96430a8" }, + { "R 0x9648004 7" }, + { "R 0x9648024" }, + { "R 0x9648040" }, + { "R 0x9648048" }, + { "R 0x9649064" }, + { "R 0x964c000" }, + { "R 0x964c030 3" }, + { "R 0x964c040 3" }, + { "R 0x964c054 2" }, + { "R 0x964c078" }, + { "R 0x964c108" }, + { "R 0x964c110" }, + { "R 0x9650020" }, + { "R 0x9651054" }, + { "R 0x9652014 3" }, + { "R 0x9652028 17" }, + { "R 0x9652070 8" }, + { "R 0x9652098" }, + { "R 0x96520a0" }, + { "R 0x96520b4" }, + { "R 0x96520c0 4" }, + { "R 0x96520f4 10" }, + { "R 0x9652120 12" }, + { "R 0x965802c" }, + { "R 0x965809c 2" }, + { "R 0x96580a8 3" }, + { "R 0x96580b8" }, + { "R 0x96580c0 7" }, + { "R 0x96580e0" }, + { "R 0x96580e8" }, + { "R 0x96580f0" }, + { "R 0x96580f8" }, + { "R 0x9658100" }, + { "R 0x9658108" }, + { "R 0x9658110" }, + { "R 0x9658118" }, + { "R 0x9658120" }, + { "R 0x9658128" }, + { "R 0x9658210 3" }, + { "R 0x9659010" }, + { "R 0x9659070" }, + { "R 0x965b004" }, + { "R 0x966004c 10" }, + { "R 0x9660078" }, + { "R 0x966020c" }, + { "R 0x9660214" }, + { "R 0x9661084" }, + { "R 0x9662020" }, + { "R 0x9663020" }, + { "R 0x9664020" }, + { "R 0x9665020" }, + { "R 0x9720344 9" }, + { "R 0x9720370 7" }, + { "R 0x9720480" }, + { "R 0x9722400 26" }, + { "R 0x9722470 5" }, + { "R 0x972320c" }, + { "R 0x9723214 2" }, + { "R 0x9723220 4" }, + { "R 0x9723308" }, + { "R 0x9723318" }, + { "R 0x972358c" }, + { "R 0x9734010" }, + { "R 0x973801c 8" }, + { "R 0x9738050" }, + { "R 0x9738100 7" }, + { "R 0x973c004" }, + { "R 0x973c014" }, + { "R 0x973c020" }, + { "R 0x973c030" }, + { "R 0x973c05c 3" }, + { "R 0x973c074" }, + { "R 0x973c088" }, + { "R 0x973c0a0" }, + { "R 0x973c0b0" }, + { "R 0x973c0c0" }, + { "R 0x973c0d0" }, + { "R 0x973c0e0" }, + { "R 0x973c0f0" }, + { "R 0x973c100" }, + { "R 0x973d064" }, + { "R 0x9740008 6" }, + { "R 0x9740028" }, + { "R 0x974203c 6" }, + { "R 0x9742058 7" }, + { "R 0x974208c" }, + { "R 0x97420b0" }, + { "R 0x97420b8 3" }, + { "R 0x97420f4" }, + { "R 0x97420fc 7" }, + { "R 0x9742324 14" }, + { "R 0x9742410" }, + { "R 0x97430a8" }, + { "R 0x9748004 7" }, + { "R 0x9748024" }, + { "R 0x9748040" }, + { "R 0x9748048" }, + { "R 0x9749064" }, + { "R 0x974c000" }, + { "R 0x974c030 3" }, + { "R 0x974c040 3" }, + { "R 0x974c054 2" }, + { "R 0x974c078" }, + { "R 0x974c108" }, + { "R 0x974c110" }, + { "R 0x9750020" }, + { "R 0x9751054" }, + { "R 0x9752014 3" }, + { "R 0x9752028 17" }, + { "R 0x9752070 8" }, + { "R 0x9752098" }, + { "R 0x97520a0" }, + { "R 0x97520b4" }, + { "R 0x97520c0 4" }, + { "R 0x97520f4 10" }, + { "R 0x9752120 12" }, + { "R 0x975802c" }, + { "R 0x975809c 2" }, + { "R 0x97580a8 3" }, + { "R 0x97580b8" }, + { "R 0x97580c0 7" }, + { "R 0x97580e0" }, + { "R 0x97580e8" }, + { "R 0x97580f0" }, + { "R 0x97580f8" }, + { "R 0x9758100" }, + { "R 0x9758108" }, + { "R 0x9758110" }, + { "R 0x9758118" }, + { "R 0x9758120" }, + { "R 0x9758128" }, + { "R 0x9758210 3" }, + { "R 0x9759010" }, + { "R 0x9759070" }, + { "R 0x975b004" }, + { "R 0x976004c 10" }, + { "R 0x9760078" }, + { "R 0x976020c" }, + { "R 0x9760214" }, + { "R 0x9761084" }, + { "R 0x9762020" }, + { "R 0x9763020" }, + { "R 0x9764020" }, + { "R 0x9765020" }, + { "R 0x92a0304" }, + { "R 0x92a0080" }, + { "R 0x92a0310" }, + { "R 0x92a0400 2" }, + { "R 0x92a0410 6" }, + { "R 0x92a0430" }, + { "R 0x92a0440" }, + { "R 0x92a0448" }, + { "R 0x92a04a0" }, + { "R 0x92a04b0 4" }, + { "R 0x92a04d0 2" }, + { "R 0x92a1400" }, + { "R 0x92a1408" }, + { "R 0x92a2400 2" }, + { "R 0x92a2438 2" }, + { "R 0x92a2454" }, + { "R 0x92a3400 4" }, + { "R 0x92a3418 3" }, + { "R 0x92a4700" }, + { "R 0x92a53b0" }, + { "R 0x92a5804" }, + { "R 0x92a590c" }, + { "R 0x92a5a14" }, + { "R 0x92a5c0c" }, + { "R 0x92a5c18 2" }, + { "R 0x92a5c2c 2" }, + { "R 0x92a5c38" }, + { "R 0x92a5c4c" }, + { "R 0x92a5ca4" }, + { "R 0x92a5cac 3" }, + { "R 0x92a6400" }, + { "R 0x92a6418 2" }, + { "R 0x92a9100" }, + { "R 0x92a9110" }, + { "R 0x92a9120" }, + { "R 0x92a9180 2" }, + { "R 0x92a91a0" }, + { "R 0x92a91b0" }, + { "R 0x92a91c0 2" }, + { "R 0x92a91e0" }, + { "R 0x93a0304" }, + { "R 0x93a0080" }, + { "R 0x93a0310" }, + { "R 0x93a0400 2" }, + { "R 0x93a0410 6" }, + { "R 0x93a0430" }, + { "R 0x93a0440" }, + { "R 0x93a0448" }, + { "R 0x93a04a0" }, + { "R 0x93a04b0 4" }, + { "R 0x93a04d0 2" }, + { "R 0x93a1400" }, + { "R 0x93a1408" }, + { "R 0x93a2400 2" }, + { "R 0x93a2438 2" }, + { "R 0x93a2454" }, + { "R 0x93a3400 4" }, + { "R 0x93a3418 3" }, + { "R 0x93a4700" }, + { "R 0x93a53b0" }, + { "R 0x93a5804" }, + { "R 0x93a590c" }, + { "R 0x93a5a14" }, + { "R 0x93a5c0c" }, + { "R 0x93a5c18 2" }, + { "R 0x93a5c2c 2" }, + { "R 0x93a5c38" }, + { "R 0x93a5c4c" }, + { "R 0x93a5ca4" }, + { "R 0x93a5cac 3" }, + { "R 0x93a6400" }, + { "R 0x93a6418 2" }, + { "R 0x93a9100" }, + { "R 0x93a9110" }, + { "R 0x93a9120" }, + { "R 0x93a9180 2" }, + { "R 0x93a91a0" }, + { "R 0x93a91b0" }, + { "R 0x93a91c0 2" }, + { "R 0x93a91e0" }, + { "R 0x94a0304" }, + { "R 0x94a0080" }, + { "R 0x94a0310" }, + { "R 0x94a0400 2" }, + { "R 0x94a0410 6" }, + { "R 0x94a0430" }, + { "R 0x94a0440" }, + { "R 0x94a0448" }, + { "R 0x94a04a0" }, + { "R 0x94a04b0 4" }, + { "R 0x94a04d0 2" }, + { "R 0x94a1400" }, + { "R 0x94a1408" }, + { "R 0x94a2400 2" }, + { "R 0x94a2438 2" }, + { "R 0x94a2454" }, + { "R 0x94a3400 4" }, + { "R 0x94a3418 3" }, + { "R 0x94a4700" }, + { "R 0x94a53b0" }, + { "R 0x94a5804" }, + { "R 0x94a590c" }, + { "R 0x94a5a14" }, + { "R 0x94a5c0c" }, + { "R 0x94a5c18 2" }, + { "R 0x94a5c2c 2" }, + { "R 0x94a5c38" }, + { "R 0x94a5c4c" }, + { "R 0x94a5ca4" }, + { "R 0x94a5cac 3" }, + { "R 0x94a6400" }, + { "R 0x94a6418 2" }, + { "R 0x94a9100" }, + { "R 0x94a9110" }, + { "R 0x94a9120" }, + { "R 0x94a9180 2" }, + { "R 0x94a91a0" }, + { "R 0x94a91b0" }, + { "R 0x94a91c0 2" }, + { "R 0x94a91e0" }, + { "R 0x95a0304" }, + { "R 0x95a0080" }, + { "R 0x95a0310" }, + { "R 0x95a0400 2" }, + { "R 0x95a0410 6" }, + { "R 0x95a0430" }, + { "R 0x95a0440" }, + { "R 0x95a0448" }, + { "R 0x95a04a0" }, + { "R 0x95a04b0 4" }, + { "R 0x95a04d0 2" }, + { "R 0x95a1400" }, + { "R 0x95a1408" }, + { "R 0x95a2400 2" }, + { "R 0x95a2438 2" }, + { "R 0x95a2454" }, + { "R 0x95a3400 4" }, + { "R 0x95a3418 3" }, + { "R 0x95a4700" }, + { "R 0x95a53b0" }, + { "R 0x95a5804" }, + { "R 0x95a590c" }, + { "R 0x95a5a14" }, + { "R 0x95a5c0c" }, + { "R 0x95a5c18 2" }, + { "R 0x95a5c2c 2" }, + { "R 0x95a5c38" }, + { "R 0x95a5c4c" }, + { "R 0x95a5ca4" }, + { "R 0x95a5cac 3" }, + { "R 0x95a6400" }, + { "R 0x95a6418 2" }, + { "R 0x95a9100" }, + { "R 0x95a9110" }, + { "R 0x95a9120" }, + { "R 0x95a9180 2" }, + { "R 0x95a91a0" }, + { "R 0x95a91b0" }, + { "R 0x95a91c0 2" }, + { "R 0x95a91e0" }, + { "R 0x96a0304" }, + { "R 0x96a0080" }, + { "R 0x96a0310" }, + { "R 0x96a0400 2" }, + { "R 0x96a0410 6" }, + { "R 0x96a0430" }, + { "R 0x96a0440" }, + { "R 0x96a0448" }, + { "R 0x96a04a0" }, + { "R 0x96a04b0 4" }, + { "R 0x96a04d0 2" }, + { "R 0x96a1400" }, + { "R 0x96a1408" }, + { "R 0x96a2400 2" }, + { "R 0x96a2438 2" }, + { "R 0x96a2454" }, + { "R 0x96a3400 4" }, + { "R 0x96a3418 3" }, + { "R 0x96a4700" }, + { "R 0x96a53b0" }, + { "R 0x96a5804" }, + { "R 0x96a590c" }, + { "R 0x96a5a14" }, + { "R 0x96a5c0c" }, + { "R 0x96a5c18 2" }, + { "R 0x96a5c2c 2" }, + { "R 0x96a5c38" }, + { "R 0x96a5c4c" }, + { "R 0x96a5ca4" }, + { "R 0x96a5cac 3" }, + { "R 0x96a6400" }, + { "R 0x96a6418 2" }, + { "R 0x96a9100" }, + { "R 0x96a9110" }, + { "R 0x96a9120" }, + { "R 0x96a9180 2" }, + { "R 0x96a91a0" }, + { "R 0x96a91b0" }, + { "R 0x96a91c0 2" }, + { "R 0x96a91e0" }, + { "R 0x97a0304" }, + { "R 0x97a0080" }, + { "R 0x97a0310" }, + { "R 0x97a0400 2" }, + { "R 0x97a0410 6" }, + { "R 0x97a0430" }, + { "R 0x97a0440" }, + { "R 0x97a0448" }, + { "R 0x97a04a0" }, + { "R 0x97a04b0 4" }, + { "R 0x97a04d0 2" }, + { "R 0x97a1400" }, + { "R 0x97a1408" }, + { "R 0x97a2400 2" }, + { "R 0x97a2438 2" }, + { "R 0x97a2454" }, + { "R 0x97a3400 4" }, + { "R 0x97a3418 3" }, + { "R 0x97a4700" }, + { "R 0x97a53b0" }, + { "R 0x97a5804" }, + { "R 0x97a590c" }, + { "R 0x97a5a14" }, + { "R 0x97a5c0c" }, + { "R 0x97a5c18 2" }, + { "R 0x97a5c2c 2" }, + { "R 0x97a5c38" }, + { "R 0x97a5c4c" }, + { "R 0x97a5ca4" }, + { "R 0x97a5cac 3" }, + { "R 0x97a6400" }, + { "R 0x97a6418 2" }, + { "R 0x97a9100" }, + { "R 0x97a9110" }, + { "R 0x97a9120" }, + { "R 0x97a9180 2" }, + { "R 0x97a91a0" }, + { "R 0x97a91b0" }, + { "R 0x97a91c0 2" }, + { "R 0x97a91e0" }, + { "R 0x9b01e64" }, + { "R 0x9b01ea0" }, + { "R 0x9b01f30 2" }, + { "R 0x9b03e64" }, + { "R 0x9b03ea0" }, + { "R 0x9b03f30 2" }, + { "R 0x9b0527c" }, + { "R 0x9b05290" }, + { "R 0x9b054ec" }, + { "R 0x9b054f4" }, + { "R 0x9b05514" }, + { "R 0x9b0551c" }, + { "R 0x9b05524" }, + { "R 0x9b05548" }, + { "R 0x9b05550" }, + { "R 0x9b05558" }, + { "R 0x9b055b8" }, + { "R 0x9b055c0" }, + { "R 0x9b055ec" }, + { "R 0x9b05860" }, + { "R 0x9b05870" }, + { "R 0x9b058a0" }, + { "R 0x9b058a8" }, + { "R 0x9b058b0" }, + { "R 0x9b058b8" }, + { "R 0x9b058d8 2" }, + { "R 0x9b058f4" }, + { "R 0x9b058fc" }, + { "R 0x9b05920" }, + { "R 0x9b05928" }, + { "R 0x9b05944" }, + { "R 0x9b06604" }, + { "R 0x9b0660c" }, + { "R 0x9b41e64" }, + { "R 0x9b41ea0" }, + { "R 0x9b41f30 2" }, + { "R 0x9b43e64" }, + { "R 0x9b43ea0" }, + { "R 0x9b43f30 2" }, + { "R 0x9b4527c" }, + { "R 0x9b45290" }, + { "R 0x9b454ec" }, + { "R 0x9b454f4" }, + { "R 0x9b45514" }, + { "R 0x9b4551c" }, + { "R 0x9b45524" }, + { "R 0x9b45548" }, + { "R 0x9b45550" }, + { "R 0x9b45558" }, + { "R 0x9b455b8" }, + { "R 0x9b455c0" }, + { "R 0x9b455ec" }, + { "R 0x9b45860" }, + { "R 0x9b45870" }, + { "R 0x9b458a0" }, + { "R 0x9b458a8" }, + { "R 0x9b458b0" }, + { "R 0x9b458b8" }, + { "R 0x9b458d8 2" }, + { "R 0x9b458f4" }, + { "R 0x9b458fc" }, + { "R 0x9b45920" }, + { "R 0x9b45928" }, + { "R 0x9b45944" }, + { "R 0x9b46604" }, + { "R 0x9b4660c" }, + { "R 0x9b81e64" }, + { "R 0x9b81ea0" }, + { "R 0x9b81f30 2" }, + { "R 0x9b83e64" }, + { "R 0x9b83ea0" }, + { "R 0x9b83f30 2" }, + { "R 0x9b8527c" }, + { "R 0x9b85290" }, + { "R 0x9b854ec" }, + { "R 0x9b854f4" }, + { "R 0x9b85514" }, + { "R 0x9b8551c" }, + { "R 0x9b85524" }, + { "R 0x9b85548" }, + { "R 0x9b85550" }, + { "R 0x9b85558" }, + { "R 0x9b855b8" }, + { "R 0x9b855c0" }, + { "R 0x9b855ec" }, + { "R 0x9b85860" }, + { "R 0x9b85870" }, + { "R 0x9b858a0" }, + { "R 0x9b858a8" }, + { "R 0x9b858b0" }, + { "R 0x9b858b8" }, + { "R 0x9b858d8 2" }, + { "R 0x9b858f4" }, + { "R 0x9b858fc" }, + { "R 0x9b85920" }, + { "R 0x9b85928" }, + { "R 0x9b85944" }, + { "R 0x9b86604" }, + { "R 0x9b8660c" }, + { "R 0x9bc1e64" }, + { "R 0x9bc1ea0" }, + { "R 0x9bc1f30 2" }, + { "R 0x9bc3e64" }, + { "R 0x9bc3ea0" }, + { "R 0x9bc3f30 2" }, + { "R 0x9bc527c" }, + { "R 0x9bc5290" }, + { "R 0x9bc54ec" }, + { "R 0x9bc54f4" }, + { "R 0x9bc5514" }, + { "R 0x9bc551c" }, + { "R 0x9bc5524" }, + { "R 0x9bc5548" }, + { "R 0x9bc5550" }, + { "R 0x9bc5558" }, + { "R 0x9bc55b8" }, + { "R 0x9bc55c0" }, + { "R 0x9bc55ec" }, + { "R 0x9bc5860" }, + { "R 0x9bc5870" }, + { "R 0x9bc58a0" }, + { "R 0x9bc58a8" }, + { "R 0x9bc58b0" }, + { "R 0x9bc58b8" }, + { "R 0x9bc58d8 2" }, + { "R 0x9bc58f4" }, + { "R 0x9bc58fc" }, + { "R 0x9bc5920" }, + { "R 0x9bc5928" }, + { "R 0x9bc5944" }, + { "R 0x9bc6604" }, + { "R 0x9bc660c" }, + { "R 0x9c01e64" }, + { "R 0x9c01ea0" }, + { "R 0x9c01f30 2" }, + { "R 0x9c03e64" }, + { "R 0x9c03ea0" }, + { "R 0x9c03f30 2" }, + { "R 0x9c0527c" }, + { "R 0x9c05290" }, + { "R 0x9c054ec" }, + { "R 0x9c054f4" }, + { "R 0x9c05514" }, + { "R 0x9c0551c" }, + { "R 0x9c05524" }, + { "R 0x9c05548" }, + { "R 0x9c05550" }, + { "R 0x9c05558" }, + { "R 0x9c055b8" }, + { "R 0x9c055c0" }, + { "R 0x9c055ec" }, + { "R 0x9c05860" }, + { "R 0x9c05870" }, + { "R 0x9c058a0" }, + { "R 0x9c058a8" }, + { "R 0x9c058b0" }, + { "R 0x9c058b8" }, + { "R 0x9c058d8 2" }, + { "R 0x9c058f4" }, + { "R 0x9c058fc" }, + { "R 0x9c05920" }, + { "R 0x9c05928" }, + { "R 0x9c05944" }, + { "R 0x9c06604" }, + { "R 0x9c0660c" }, + { "R 0x9c41e64" }, + { "R 0x9c41ea0" }, + { "R 0x9c41f30 2" }, + { "R 0x9c43e64" }, + { "R 0x9c43ea0" }, + { "R 0x9c43f30 2" }, + { "R 0x9c4527c" }, + { "R 0x9c45290" }, + { "R 0x9c454ec" }, + { "R 0x9c454f4" }, + { "R 0x9c45514" }, + { "R 0x9c4551c" }, + { "R 0x9c45524" }, + { "R 0x9c45548" }, + { "R 0x9c45550" }, + { "R 0x9c45558" }, + { "R 0x9c455b8" }, + { "R 0x9c455c0" }, + { "R 0x9c455ec" }, + { "R 0x9c45860" }, + { "R 0x9c45870" }, + { "R 0x9c458a0" }, + { "R 0x9c458a8" }, + { "R 0x9c458b0" }, + { "R 0x9c458b8" }, + { "R 0x9c458d8 2" }, + { "R 0x9c458f4" }, + { "R 0x9c458fc" }, + { "R 0x9c45920" }, + { "R 0x9c45928" }, + { "R 0x9c45944" }, + { "R 0x9c46604" }, + { "R 0x9c4660c" }, +}; + +static const struct dcc_link_config lemans_link_configs[] = { + { + .link_list = 6, + .entries = lemans_dcc_entries, + .num_entries = ARRAY_SIZE(lemans_dcc_entries), + }, +}; + +static const struct dcc_config lemans_config = { + .lists = lemans_link_configs, + .num_lists = ARRAY_SIZE(lemans_link_configs), +}; + +static const struct dcc_pdata lemans_pdata = { + .base = 0x040ff000, + .size = 0x00001000, + .ram_base = 0x040b8800, + .ram_size = 0x00006000, + .dcc_offset = 0x38800, + .map_ver = 0x3, + .config = &lemans_config, +}; + +#endif /* _QCOM_DCC_LEMANS_CONFIG_H */ From 3feb4d9e64e2f54665c8d5b9617d78b7180197a3 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 11:34:33 +0800 Subject: [PATCH 0022/1058] QCLINUX: qcom-dcc: move talos config to qcom-dcc-talos-config.h Move the talos DCC configuration (entries array, link config, dcc config, and pdata) into a dedicated header qcom-dcc-talos-config.h, consistent with the approach used for the lemans config. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 782 +------------------------- drivers/misc/qcom-dcc-talos-config.h | 792 +++++++++++++++++++++++++++ 2 files changed, 793 insertions(+), 781 deletions(-) create mode 100644 drivers/misc/qcom-dcc-talos-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index d3dcda2d3e5fc..83efad89b4d76 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -7,793 +7,13 @@ #include #include #include "qcom-dcc.h" +#include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_register_entry talos_dcc_entries[] = { - { "R 0x9680000" }, - { "R 0x9680004" }, - { "R 0x9681000" }, - { "R 0x9681004" }, - { "R 0x9681008" }, - { "R 0x968100c" }, - { "R 0x9681010" }, - { "R 0x9681014" }, - { "R 0x968101c" }, - { "R 0x9681020" }, - { "R 0x9681024" }, - { "R 0x9681028" }, - { "R 0x968102c" }, - { "R 0x9681030" }, - { "R 0x9681034" }, - { "R 0x968103c" }, - { "R 0x9698100" }, - { "R 0x9698104" }, - { "R 0x9698108" }, - { "R 0x9698110" }, - { "R 0x9698120" }, - { "R 0x9698124" }, - { "R 0x9698128" }, - { "R 0x969812c" }, - { "R 0x9698130" }, - { "R 0x9698134" }, - { "R 0x9698138" }, - { "R 0x969813c" }, - { "R 0x9698500" }, - { "R 0x9698504" }, - { "R 0x9698508" }, - { "R 0x969850c" }, - { "R 0x9698510" }, - { "R 0x9698514" }, - { "R 0x9698518" }, - { "R 0x969851c" }, - { "R 0x9698700" }, - { "R 0x9698704" }, - { "R 0x9698708" }, - { "R 0x969870c" }, - { "R 0x9698714" }, - { "R 0x9698718" }, - { "R 0x969871c" }, - { "R 0x1620204" }, - { "R 0x1620240" }, - { "R 0x1620248" }, - { "R 0x1620288" }, - { "R 0x162028C" }, - { "R 0x1620290" }, - { "R 0x1620294" }, - { "R 0x16202A8" }, - { "R 0x16202AC" }, - { "R 0x16202B0" }, - { "R 0x16202B4" }, - { "R 0x1620300" }, - { "R 0x1700204" }, - { "R 0x1700240" }, - { "R 0x1700248" }, - { "R 0x1700288" }, - { "R 0x1700290" }, - { "R 0x1700300" }, - { "R 0x1700304" }, - { "R 0x1700308" }, - { "R 0x170030C" }, - { "R 0x1700310" }, - { "R 0x1700314" }, - { "R 0x1700C08" }, - { "R 0x1700C10" }, - { "R 0x1700C20" }, - { "R 0x1700C24" }, - { "R 0x1700C28" }, - { "R 0x1700C2C" }, - { "R 0x1700C30" }, - { "R 0x1700C34" }, - { "R 0x1700C38" }, - { "R 0x1700C3C" }, - { "R 0x1740240" }, - { "R 0x1740248" }, - { "R 0x1740288" }, - { "R 0x1740290" }, - { "R 0x1740300" }, - { "R 0x1740304" }, - { "R 0x1740308" }, - { "R 0x174030C" }, - { "R 0x1740310" }, - { "R 0x1740314" }, - { "R 0x1740004" }, - { "R 0x1740008" }, - { "R 0x1740010" }, - { "R 0x1740020" }, - { "R 0x1740024" }, - { "R 0x1740028" }, - { "R 0x174002C" }, - { "R 0x1740030" }, - { "R 0x1740034" }, - { "R 0x1740038" }, - { "R 0x174003C" }, - { "R 0x9698204" }, - { "R 0x9698240" }, - { "R 0x9698244" }, - { "R 0x9698248" }, - { "R 0x969824C" }, - { "R 0x9681010" }, - { "R 0x9681014" }, - { "R 0x9681018" }, - { "R 0x968101C" }, - { "R 0x9681020" }, - { "R 0x9681024" }, - { "R 0x9681028" }, - { "R 0x968102C" }, - { "R 0x9681030" }, - { "R 0x9681034" }, - { "R 0x968103C" }, - { "R 0x9698100" }, - { "R 0x9698104" }, - { "R 0x9698108" }, - { "R 0x9698110" }, - { "R 0x9698120" }, - { "R 0x9698124" }, - { "R 0x9698128" }, - { "R 0x969812C" }, - { "R 0x9698130" }, - { "R 0x9698134" }, - { "R 0x9698138" }, - { "R 0x969813C" }, - { "R 0x62BE2004" }, - { "R 0x62BE2040" }, - { "R 0x62BE2048" }, - { "R 0x62BE2088" }, - { "R 0x62BE2090" }, - { "R 0x62BE2100" }, - { "R 0x62BE2104" }, - { "R 0x62BE2108" }, - { "R 0x62BE210C" }, - { "R 0x62BE2110" }, - { "R 0x62BE2114" }, - { "R 0x62BE2118" }, - { "R 0x62BE0010" }, - { "R 0x62BE0020" }, - { "R 0x62BE0024" }, - { "R 0x62BE0028" }, - { "R 0x62BE002C" }, - { "R 0x62BE0030" }, - { "R 0x62BE0034" }, - { "R 0x62BE0038" }, - { "R 0x62BE003C" }, - { "R 0x9160204" }, - { "R 0x9160240" }, - { "R 0x9160248" }, - { "R 0x9160288" }, - { "R 0x9160290" }, - { "R 0x9160300" }, - { "R 0x9160304" }, - { "R 0x9160308" }, - { "R 0x916030C" }, - { "R 0x9160310" }, - { "R 0x9160314" }, - { "R 0x9160318" }, - { "R 0x9160008" }, - { "R 0x9160010" }, - { "R 0x9160020" }, - { "R 0x9160024" }, - { "R 0x9160028" }, - { "R 0x916002C" }, - { "R 0x9160030" }, - { "R 0x9160034" }, - { "R 0x9160038" }, - { "R 0x916003C" }, - { "R 0x1620500 4" }, - { "R 0x1620700 4" }, - { "R 0x1620300" }, - { "R 0x1620F00 2" }, - { "R 0x1620B00 2" }, - { "R 0x1700B00 2" }, - { "R 0x1700700 3" }, - { "R 0x9163100" }, - { "R 0x96AA100" }, - { "R 0x9050008" }, - { "R 0x9050068" }, - { "R 0x9050078" }, - { "R 0x18200400" }, - { "R 0x18200404" }, - { "R 0x18200408" }, - { "R 0x18200038" }, - { "R 0x18200040" }, - { "R 0x18200048" }, - { "R 0x18220038" }, - { "R 0x18220040" }, - { "R 0x182200D0" }, - { "R 0x18200030" }, - { "R 0x18200010" }, - { "R 0x1822000c" }, - { "R 0x18220d14" }, - { "R 0x18220fb4" }, - { "R 0x18221254" }, - { "R 0x182214f4" }, - { "R 0x18221794" }, - { "R 0x18221a34" }, - { "R 0x18221cd4" }, - { "R 0x18221f74" }, - { "R 0x18220d18" }, - { "R 0x18220fb8" }, - { "R 0x18221258" }, - { "R 0x182214f8" }, - { "R 0x18221798" }, - { "R 0x18221a38" }, - { "R 0x18221cd8" }, - { "R 0x18221f78" }, - { "R 0x18220d00" }, - { "R 0x18220d04" }, - { "R 0x18220d1c" }, - { "R 0x18220fbc" }, - { "R 0x1822125c" }, - { "R 0x182214fc" }, - { "R 0x1822179c" }, - { "R 0x18221a3c" }, - { "R 0x18221cdc" }, - { "R 0x18221f7c" }, - { "R 0x18221274" }, - { "R 0x18221288" }, - { "R 0x1822129c" }, - { "R 0x182212b0" }, - { "R 0x182212c4" }, - { "R 0x182212d8" }, - { "R 0x182212ec" }, - { "R 0x18221300" }, - { "R 0x18221314" }, - { "R 0x18221328" }, - { "R 0x1822133c" }, - { "R 0x18221350" }, - { "R 0x18221364" }, - { "R 0x18221378" }, - { "R 0x1822138c" }, - { "R 0x182213a0" }, - { "R 0x18221514" }, - { "R 0x18221528" }, - { "R 0x1822153c" }, - { "R 0x18221550" }, - { "R 0x18221564" }, - { "R 0x18221578" }, - { "R 0x1822158c" }, - { "R 0x182215a0" }, - { "R 0x182215b4" }, - { "R 0x182215c8" }, - { "R 0x182215dc" }, - { "R 0x182215f0" }, - { "R 0x18221604" }, - { "R 0x18221618" }, - { "R 0x1822162c" }, - { "R 0x18221640" }, - { "R 0x182217b4" }, - { "R 0x182217c8" }, - { "R 0x182217dc" }, - { "R 0x182217f0" }, - { "R 0x18221804" }, - { "R 0x18221818" }, - { "R 0x1822182c" }, - { "R 0x18221840" }, - { "R 0x18221854" }, - { "R 0x18221868" }, - { "R 0x1822187c" }, - { "R 0x18221890" }, - { "R 0x182218a4" }, - { "R 0x182218b8" }, - { "R 0x182218cc" }, - { "R 0x182218e0" }, - { "R 0x18221a54" }, - { "R 0x18221a68" }, - { "R 0x18221a7c" }, - { "R 0x18221a90" }, - { "R 0x18221aa4" }, - { "R 0x18221ab8" }, - { "R 0x18221acc" }, - { "R 0x18221ae0" }, - { "R 0x18221af4" }, - { "R 0x18221b08" }, - { "R 0x18221b1c" }, - { "R 0x18221b30" }, - { "R 0x18221b44" }, - { "R 0x18221b58" }, - { "R 0x18221b6c" }, - { "R 0x18221b80" }, - { "R 0x18221cf4" }, - { "R 0x18221d08" }, - { "R 0x18221d1c" }, - { "R 0x18221d30" }, - { "R 0x18221d44" }, - { "R 0x18221d58" }, - { "R 0x18221d6c" }, - { "R 0x18221d80" }, - { "R 0x18221d94" }, - { "R 0x18221da8" }, - { "R 0x18221dbc" }, - { "R 0x18221dd0" }, - { "R 0x18221de4" }, - { "R 0x18221df8" }, - { "R 0x18221e0c" }, - { "R 0x18221e20" }, - { "R 0x18221f94" }, - { "R 0x18221fa8" }, - { "R 0x18221fbc" }, - { "R 0x18221fd0" }, - { "R 0x18221fe4" }, - { "R 0x18221ff8" }, - { "R 0x1822200c" }, - { "R 0x18222020" }, - { "R 0x18222034" }, - { "R 0x18222048" }, - { "R 0x1822205c" }, - { "R 0x18222070" }, - { "R 0x18222084" }, - { "R 0x18222098" }, - { "R 0x182220ac" }, - { "R 0x182220c0" }, - { "R 0x18221278" }, - { "R 0x1822128c" }, - { "R 0x182212a0" }, - { "R 0x182212b4" }, - { "R 0x182212c8" }, - { "R 0x182212dc" }, - { "R 0x182212f0" }, - { "R 0x18221304" }, - { "R 0x18221318" }, - { "R 0x1822132c" }, - { "R 0x18221340" }, - { "R 0x18221354" }, - { "R 0x18221368" }, - { "R 0x1822137c" }, - { "R 0x18221390" }, - { "R 0x182213a4" }, - { "R 0x18221518" }, - { "R 0x1822152c" }, - { "R 0x18221540" }, - { "R 0x18221554" }, - { "R 0x18221568" }, - { "R 0x1822157c" }, - { "R 0x18221590" }, - { "R 0x182215a4" }, - { "R 0x182215b8" }, - { "R 0x182215cc" }, - { "R 0x182215e0" }, - { "R 0x182215f4" }, - { "R 0x18221608" }, - { "R 0x1822161c" }, - { "R 0x18221630" }, - { "R 0x18221644" }, - { "R 0x182217b8" }, - { "R 0x182217cc" }, - { "R 0x182217e0" }, - { "R 0x182217f4" }, - { "R 0x18221808" }, - { "R 0x1822181c" }, - { "R 0x18221830" }, - { "R 0x18221844" }, - { "R 0x18221858" }, - { "R 0x1822186c" }, - { "R 0x18221880" }, - { "R 0x18221894" }, - { "R 0x182218a8" }, - { "R 0x182218bc" }, - { "R 0x182218d0" }, - { "R 0x182218e4" }, - { "R 0x18221a58" }, - { "R 0x18221a6c" }, - { "R 0x18221a80" }, - { "R 0x18221a94" }, - { "R 0x18221aa8" }, - { "R 0x18221abc" }, - { "R 0x18221ad0" }, - { "R 0x18221ae4" }, - { "R 0x18221af8" }, - { "R 0x18221b0c" }, - { "R 0x18221b20" }, - { "R 0x18221b34" }, - { "R 0x18221b48" }, - { "R 0x18221b5c" }, - { "R 0x18221b70" }, - { "R 0x18221b84" }, - { "R 0x18221cf8" }, - { "R 0x18221d0c" }, - { "R 0x18221d20" }, - { "R 0x18221d34" }, - { "R 0x18221d48" }, - { "R 0x18221d5c" }, - { "R 0x18221d70" }, - { "R 0x18221d84" }, - { "R 0x18221d98" }, - { "R 0x18221dac" }, - { "R 0x18221dc0" }, - { "R 0x18221dd4" }, - { "R 0x18221de8" }, - { "R 0x18221dfc" }, - { "R 0x18221e10" }, - { "R 0x18221e24" }, - { "R 0x18221f98" }, - { "R 0x18221fac" }, - { "R 0x18221fc0" }, - { "R 0x18221fd4" }, - { "R 0x18221fe8" }, - { "R 0x18221ffc" }, - { "R 0x18222010" }, - { "R 0x18222024" }, - { "R 0x18222038" }, - { "R 0x1822204c" }, - { "R 0x18222060" }, - { "R 0x18222074" }, - { "R 0x18222088" }, - { "R 0x1822209c" }, - { "R 0x182220b0" }, - { "R 0x182220c4" }, - { "R 0x18000024" }, - { "R 0x18000040" }, - { "R 0x18010024" }, - { "R 0x18010040" }, - { "R 0x18020024" }, - { "R 0x18020040" }, - { "R 0x18030024" }, - { "R 0x18030040" }, - { "R 0x18040024" }, - { "R 0x18040040" }, - { "R 0x18050024" }, - { "R 0x18050040" }, - { "R 0x18060024" }, - { "R 0x18060040" }, - { "R 0x18070024" }, - { "R 0x18070040" }, - { "R 0x18080024" }, - { "R 0x18080040" }, - { "R 0x180800F8" }, - { "R 0x18080104" }, - { "R 0x1808011C" }, - { "R 0x18080128" }, - { "R 0x90b0280" }, - { "R 0x90b0288" }, - { "R 0x90b028c" }, - { "R 0x90b0290" }, - { "R 0x90b0294" }, - { "R 0x90b0298" }, - { "R 0x90b029c" }, - { "R 0x90b02a0" }, - { "R 0x18321700" }, - { "R 0x18322C18" }, - { "R 0x18323700" }, - { "R 0x18324C18" }, - { "R 0x18325F00" }, - { "R 0x18327418" }, - { "R 0x9236028" }, - { "R 0x923602C" }, - { "R 0x9236030" }, - { "R 0x9236034" }, - { "R 0x9236038" }, - { "R 0x9232100" }, - { "R 0x92360b0" }, - { "R 0x9236044" }, - { "R 0x9236048" }, - { "R 0x923604c" }, - { "R 0x9236050" }, - { "R 0x923e030" }, - { "R 0x923e034" }, - { "R 0x9241000" }, - { "R 0x9248058" }, - { "R 0x924805c" }, - { "R 0x9248060" }, - { "R 0x9248064" }, - { "R 0x9260410" }, - { "R 0x92e0410" }, - { "R 0x9260414" }, - { "R 0x92e0414" }, - { "R 0x9260418" }, - { "R 0x92e0418" }, - { "R 0x9260420" }, - { "R 0x9260424" }, - { "R 0x9260430" }, - { "R 0x9260440" }, - { "R 0x9260448" }, - { "R 0x92604a0" }, - { "R 0x92e0420" }, - { "R 0x92e0424" }, - { "R 0x92e0430" }, - { "R 0x92e0440" }, - { "R 0x92e0448" }, - { "R 0x92e04a0" }, - { "R 0x9600000" }, - { "R 0x9601000" }, - { "R 0x9602000" }, - { "R 0x9603000" }, - { "R 0x9604000" }, - { "R 0x9605000" }, - { "R 0x9606000" }, - { "R 0x9607000" }, - { "R 0x9608000" }, - { "R 0x9609000" }, - { "R 0x960a000" }, - { "R 0x960b000" }, - { "R 0x960c000" }, - { "R 0x960d000" }, - { "R 0x960e000" }, - { "R 0x960f000" }, - { "R 0x9610000" }, - { "R 0x9611000" }, - { "R 0x9612000" }, - { "R 0x9613000" }, - { "R 0x9614000" }, - { "R 0x9615000" }, - { "R 0x9616000" }, - { "R 0x9617000" }, - { "R 0x9618000" }, - { "R 0x9619000" }, - { "R 0x961a000" }, - { "R 0x961b000" }, - { "R 0x961c000" }, - { "R 0x961d000" }, - { "R 0x961e000" }, - { "R 0x961f000" }, - { "R 0x9600004" }, - { "R 0x9601004" }, - { "R 0x9602004" }, - { "R 0x9603004" }, - { "R 0x9604004" }, - { "R 0x9605004" }, - { "R 0x9606004" }, - { "R 0x9607004" }, - { "R 0x9608004" }, - { "R 0x9609004" }, - { "R 0x960a004" }, - { "R 0x960b004" }, - { "R 0x960c004" }, - { "R 0x960d004" }, - { "R 0x960e004" }, - { "R 0x960f004" }, - { "R 0x9610004" }, - { "R 0x9611004" }, - { "R 0x9612004" }, - { "R 0x9613004" }, - { "R 0x9614004" }, - { "R 0x9615004" }, - { "R 0x9616004" }, - { "R 0x9617004" }, - { "R 0x9618004" }, - { "R 0x9619004" }, - { "R 0x961a004" }, - { "R 0x961b004" }, - { "R 0x961c004" }, - { "R 0x961d004" }, - { "R 0x961e004" }, - { "R 0x961f004" }, - { "R 0x9266418" }, - { "R 0x92e6418" }, - { "R 0x9265804" }, - { "R 0x92e5804" }, - { "R 0x92604b8" }, - { "R 0x92e04b8" }, - { "R 0x0C201244 1" }, - { "R 0x0C202244 1" }, - { "R 0x18100C18 1" }, - { "R 0x18101C18 1" }, - { "R 0x18300000 1" }, - { "R 0x183A3A84 2" }, - { "R 0x18393A84 2" }, - { "R 0x00100000" }, - { "R 0x00100004" }, - { "R 0x00100008" }, - { "R 0x0010000C" }, - { "R 0x00100010" }, - { "R 0x00100014" }, - { "R 0x00100018" }, - { "R 0x0010001C" }, - { "R 0x00100020" }, - { "R 0x00100024" }, - { "R 0x00100028" }, - { "R 0x0010002C" }, - { "R 0x00100030" }, - { "R 0x00100034" }, - { "R 0x00100100" }, - { "R 0x00100104" }, - { "R 0x00100108" }, - { "R 0x0010010C" }, - { "R 0x00101000" }, - { "R 0x00101004" }, - { "R 0x00101008" }, - { "R 0x0010100C" }, - { "R 0x00101010" }, - { "R 0x00101014" }, - { "R 0x00101018" }, - { "R 0x0010101C" }, - { "R 0x00101020" }, - { "R 0x00101024" }, - { "R 0x00101028" }, - { "R 0x0010102C" }, - { "R 0x00101030" }, - { "R 0x00101034" }, - { "R 0x00102000" }, - { "R 0x00102004" }, - { "R 0x00102008" }, - { "R 0x0010200C" }, - { "R 0x00102010" }, - { "R 0x00102014" }, - { "R 0x00102018" }, - { "R 0x0010201C" }, - { "R 0x00102020" }, - { "R 0x00102024" }, - { "R 0x00102028" }, - { "R 0x0010202C" }, - { "R 0x00102030" }, - { "R 0x00102034" }, - { "R 0x00103000" }, - { "R 0x00103004" }, - { "R 0x00103008" }, - { "R 0x0010300C" }, - { "R 0x00103010" }, - { "R 0x00103014" }, - { "R 0x00103018" }, - { "R 0x0010301C" }, - { "R 0x00103020" }, - { "R 0x00103024" }, - { "R 0x00103028" }, - { "R 0x0010302C" }, - { "R 0x00103030" }, - { "R 0x00103034" }, - { "R 0x00113000" }, - { "R 0x00113004" }, - { "R 0x00113008" }, - { "R 0x0011300C" }, - { "R 0x00113010" }, - { "R 0x00113014" }, - { "R 0x00113018" }, - { "R 0x0011301C" }, - { "R 0x00113020" }, - { "R 0x00113024" }, - { "R 0x00113028" }, - { "R 0x0011302C" }, - { "R 0x00113030" }, - { "R 0x00113034" }, - { "R 0x0011A000" }, - { "R 0x0011A004" }, - { "R 0x0011A008" }, - { "R 0x0011A00C" }, - { "R 0x0011A010" }, - { "R 0x0011A014" }, - { "R 0x0011A018" }, - { "R 0x0011A01C" }, - { "R 0x0011A020" }, - { "R 0x0011A024" }, - { "R 0x0011A028" }, - { "R 0x0011A02C" }, - { "R 0x0011A030" }, - { "R 0x0011A034" }, - { "R 0x0011B000" }, - { "R 0x0011B004" }, - { "R 0x0011B008" }, - { "R 0x0011B00C" }, - { "R 0x0011B010" }, - { "R 0x0011B014" }, - { "R 0x0011B018" }, - { "R 0x0011B01C" }, - { "R 0x0011B020" }, - { "R 0x0011B024" }, - { "R 0x0011B028" }, - { "R 0x0011B02C" }, - { "R 0x0011B030" }, - { "R 0x0011B034" }, - { "R 0x00174000" }, - { "R 0x00174004" }, - { "R 0x00174008" }, - { "R 0x0017400C" }, - { "R 0x00174010" }, - { "R 0x00174014" }, - { "R 0x00174018" }, - { "R 0x0017401C" }, - { "R 0x00174020" }, - { "R 0x00174024" }, - { "R 0x00174028" }, - { "R 0x0017402C" }, - { "R 0x00174030" }, - { "R 0x00174034" }, - { "R 0x00176000" }, - { "R 0x00176004" }, - { "R 0x00176008" }, - { "R 0x0017600C" }, - { "R 0x00176010" }, - { "R 0x00176014" }, - { "R 0x00176018" }, - { "R 0x0017601C" }, - { "R 0x00176020" }, - { "R 0x00176024" }, - { "R 0x00176028" }, - { "R 0x0017602C" }, - { "R 0x00176030" }, - { "R 0x00176034" }, - { "R 0x0010401C" }, - { "R 0x00183024" }, - { "R 0x00144168" }, - { "R 0x0011702C" }, - { "R 0x0010904C" }, - { "R 0x00189038" }, - { "R 0x001443E8" }, - { "R 0x001442B8" }, - { "R 0x00105060" }, - { "R 0x00141024" }, - { "R 0x00145038" }, - { "R 0x00109004" }, - { "R 0x00189004" }, - { "R 0x00190004" }, - { "R 0x0C2A0000" }, - { "R 0x0C2A0004" }, - { "R 0x0C2A0008" }, - { "R 0x0C2A000C" }, - { "R 0x0C2A0010" }, - { "R 0x0C2A0014" }, - { "R 0x0C2A0018" }, - { "R 0x0C2A001C" }, - { "R 0x0C2A0020" }, - { "R 0x0C2A0024" }, - { "R 0x0C2A0028" }, - { "R 0x0C2A002C" }, - { "R 0x0C2A0030" }, - { "R 0x0C2A0034" }, - { "R 0x0C2A1000" }, - { "R 0x0C2A1004" }, - { "R 0x0C2A1008" }, - { "R 0x0C2A100C" }, - { "R 0x0C2A1010" }, - { "R 0x0C2A1014" }, - { "R 0x0C2A1018" }, - { "R 0x0C2A101C" }, - { "R 0x0C2A1020" }, - { "R 0x0C2A1024" }, - { "R 0x0C2A1028" }, - { "R 0x0C2A102C" }, - { "R 0x0C2A1030" }, - { "R 0x0C2A2260" }, - { "R 0x0C2A2264" }, - { "R 0x0C2A3008" }, - { "R 0x0C2A300C" }, - { "R 0x0C2A3010" }, - { "R 0x0C2A3014" }, - { "R 0x0C2A3024" }, - { "R 0x0C2A2034" }, - { "R 0x0C2A214C" }, - { "R 0x0C2A2150" }, - { "R 0x0C2A2154" }, - { "R 0x0C2630A0 4" }, - { "R 0x0C2630B0 4" }, - { "R 0x0C2630C0 4" }, - { "R 0x0C2630D0 4" }, - { "R 0x1800005C 1" }, - { "R 0x1801005C 1" }, - { "R 0x1802005C 1" }, - { "R 0x1803005C 1" }, - { "R 0x1804005C 1" }, - { "R 0x1805005C 1" }, - { "R 0x1806005C 1" }, - { "R 0x1807005C 1" }, - { "R 0x3d96000" }, - { "R 0x3d96004" }, -}; - -static const struct dcc_link_config talos_link_configs[] = { - { - .link_list = 3, - .entries = talos_dcc_entries, - .num_entries = ARRAY_SIZE(talos_dcc_entries), - }, -}; - -static const struct dcc_config talos_config = { - .lists = talos_link_configs, - .num_lists = ARRAY_SIZE(talos_link_configs), -}; - -static const struct dcc_pdata talos_pdata = { - .base = 0x010a2000, - .size = 0x00001000, - .ram_base = 0x010ae000, - .ram_size = 0x00002000, - .dcc_offset = 0x6000, - .map_ver = 0x1, - .config = &talos_config, -}; - static const struct dcc_pdata kodiak_pdata = { .base = 0x0117f000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-talos-config.h b/drivers/misc/qcom-dcc-talos-config.h new file mode 100644 index 0000000000000..2c2316ae37853 --- /dev/null +++ b/drivers/misc/qcom-dcc-talos-config.h @@ -0,0 +1,792 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_TALOS_CONFIG_H +#define _QCOM_DCC_TALOS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x9680000" }, + { "R 0x9680004" }, + { "R 0x9681000" }, + { "R 0x9681004" }, + { "R 0x9681008" }, + { "R 0x968100c" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x968101c" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102c" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103c" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812c" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813c" }, + { "R 0x9698500" }, + { "R 0x9698504" }, + { "R 0x9698508" }, + { "R 0x969850c" }, + { "R 0x9698510" }, + { "R 0x9698514" }, + { "R 0x9698518" }, + { "R 0x969851c" }, + { "R 0x9698700" }, + { "R 0x9698704" }, + { "R 0x9698708" }, + { "R 0x969870c" }, + { "R 0x9698714" }, + { "R 0x9698718" }, + { "R 0x969871c" }, + { "R 0x1620204" }, + { "R 0x1620240" }, + { "R 0x1620248" }, + { "R 0x1620288" }, + { "R 0x162028C" }, + { "R 0x1620290" }, + { "R 0x1620294" }, + { "R 0x16202A8" }, + { "R 0x16202AC" }, + { "R 0x16202B0" }, + { "R 0x16202B4" }, + { "R 0x1620300" }, + { "R 0x1700204" }, + { "R 0x1700240" }, + { "R 0x1700248" }, + { "R 0x1700288" }, + { "R 0x1700290" }, + { "R 0x1700300" }, + { "R 0x1700304" }, + { "R 0x1700308" }, + { "R 0x170030C" }, + { "R 0x1700310" }, + { "R 0x1700314" }, + { "R 0x1700C08" }, + { "R 0x1700C10" }, + { "R 0x1700C20" }, + { "R 0x1700C24" }, + { "R 0x1700C28" }, + { "R 0x1700C2C" }, + { "R 0x1700C30" }, + { "R 0x1700C34" }, + { "R 0x1700C38" }, + { "R 0x1700C3C" }, + { "R 0x1740240" }, + { "R 0x1740248" }, + { "R 0x1740288" }, + { "R 0x1740290" }, + { "R 0x1740300" }, + { "R 0x1740304" }, + { "R 0x1740308" }, + { "R 0x174030C" }, + { "R 0x1740310" }, + { "R 0x1740314" }, + { "R 0x1740004" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020" }, + { "R 0x1740024" }, + { "R 0x1740028" }, + { "R 0x174002C" }, + { "R 0x1740030" }, + { "R 0x1740034" }, + { "R 0x1740038" }, + { "R 0x174003C" }, + { "R 0x9698204" }, + { "R 0x9698240" }, + { "R 0x9698244" }, + { "R 0x9698248" }, + { "R 0x969824C" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x9681018" }, + { "R 0x968101C" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102C" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103C" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812C" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813C" }, + { "R 0x62BE2004" }, + { "R 0x62BE2040" }, + { "R 0x62BE2048" }, + { "R 0x62BE2088" }, + { "R 0x62BE2090" }, + { "R 0x62BE2100" }, + { "R 0x62BE2104" }, + { "R 0x62BE2108" }, + { "R 0x62BE210C" }, + { "R 0x62BE2110" }, + { "R 0x62BE2114" }, + { "R 0x62BE2118" }, + { "R 0x62BE0010" }, + { "R 0x62BE0020" }, + { "R 0x62BE0024" }, + { "R 0x62BE0028" }, + { "R 0x62BE002C" }, + { "R 0x62BE0030" }, + { "R 0x62BE0034" }, + { "R 0x62BE0038" }, + { "R 0x62BE003C" }, + { "R 0x9160204" }, + { "R 0x9160240" }, + { "R 0x9160248" }, + { "R 0x9160288" }, + { "R 0x9160290" }, + { "R 0x9160300" }, + { "R 0x9160304" }, + { "R 0x9160308" }, + { "R 0x916030C" }, + { "R 0x9160310" }, + { "R 0x9160314" }, + { "R 0x9160318" }, + { "R 0x9160008" }, + { "R 0x9160010" }, + { "R 0x9160020" }, + { "R 0x9160024" }, + { "R 0x9160028" }, + { "R 0x916002C" }, + { "R 0x9160030" }, + { "R 0x9160034" }, + { "R 0x9160038" }, + { "R 0x916003C" }, + { "R 0x1620500 4" }, + { "R 0x1620700 4" }, + { "R 0x1620300" }, + { "R 0x1620F00 2" }, + { "R 0x1620B00 2" }, + { "R 0x1700B00 2" }, + { "R 0x1700700 3" }, + { "R 0x9163100" }, + { "R 0x96AA100" }, + { "R 0x9050008" }, + { "R 0x9050068" }, + { "R 0x9050078" }, + { "R 0x18200400" }, + { "R 0x18200404" }, + { "R 0x18200408" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200D0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + { "R 0x1822000c" }, + { "R 0x18220d14" }, + { "R 0x18220fb4" }, + { "R 0x18221254" }, + { "R 0x182214f4" }, + { "R 0x18221794" }, + { "R 0x18221a34" }, + { "R 0x18221cd4" }, + { "R 0x18221f74" }, + { "R 0x18220d18" }, + { "R 0x18220fb8" }, + { "R 0x18221258" }, + { "R 0x182214f8" }, + { "R 0x18221798" }, + { "R 0x18221a38" }, + { "R 0x18221cd8" }, + { "R 0x18221f78" }, + { "R 0x18220d00" }, + { "R 0x18220d04" }, + { "R 0x18220d1c" }, + { "R 0x18220fbc" }, + { "R 0x1822125c" }, + { "R 0x182214fc" }, + { "R 0x1822179c" }, + { "R 0x18221a3c" }, + { "R 0x18221cdc" }, + { "R 0x18221f7c" }, + { "R 0x18221274" }, + { "R 0x18221288" }, + { "R 0x1822129c" }, + { "R 0x182212b0" }, + { "R 0x182212c4" }, + { "R 0x182212d8" }, + { "R 0x182212ec" }, + { "R 0x18221300" }, + { "R 0x18221314" }, + { "R 0x18221328" }, + { "R 0x1822133c" }, + { "R 0x18221350" }, + { "R 0x18221364" }, + { "R 0x18221378" }, + { "R 0x1822138c" }, + { "R 0x182213a0" }, + { "R 0x18221514" }, + { "R 0x18221528" }, + { "R 0x1822153c" }, + { "R 0x18221550" }, + { "R 0x18221564" }, + { "R 0x18221578" }, + { "R 0x1822158c" }, + { "R 0x182215a0" }, + { "R 0x182215b4" }, + { "R 0x182215c8" }, + { "R 0x182215dc" }, + { "R 0x182215f0" }, + { "R 0x18221604" }, + { "R 0x18221618" }, + { "R 0x1822162c" }, + { "R 0x18221640" }, + { "R 0x182217b4" }, + { "R 0x182217c8" }, + { "R 0x182217dc" }, + { "R 0x182217f0" }, + { "R 0x18221804" }, + { "R 0x18221818" }, + { "R 0x1822182c" }, + { "R 0x18221840" }, + { "R 0x18221854" }, + { "R 0x18221868" }, + { "R 0x1822187c" }, + { "R 0x18221890" }, + { "R 0x182218a4" }, + { "R 0x182218b8" }, + { "R 0x182218cc" }, + { "R 0x182218e0" }, + { "R 0x18221a54" }, + { "R 0x18221a68" }, + { "R 0x18221a7c" }, + { "R 0x18221a90" }, + { "R 0x18221aa4" }, + { "R 0x18221ab8" }, + { "R 0x18221acc" }, + { "R 0x18221ae0" }, + { "R 0x18221af4" }, + { "R 0x18221b08" }, + { "R 0x18221b1c" }, + { "R 0x18221b30" }, + { "R 0x18221b44" }, + { "R 0x18221b58" }, + { "R 0x18221b6c" }, + { "R 0x18221b80" }, + { "R 0x18221cf4" }, + { "R 0x18221d08" }, + { "R 0x18221d1c" }, + { "R 0x18221d30" }, + { "R 0x18221d44" }, + { "R 0x18221d58" }, + { "R 0x18221d6c" }, + { "R 0x18221d80" }, + { "R 0x18221d94" }, + { "R 0x18221da8" }, + { "R 0x18221dbc" }, + { "R 0x18221dd0" }, + { "R 0x18221de4" }, + { "R 0x18221df8" }, + { "R 0x18221e0c" }, + { "R 0x18221e20" }, + { "R 0x18221f94" }, + { "R 0x18221fa8" }, + { "R 0x18221fbc" }, + { "R 0x18221fd0" }, + { "R 0x18221fe4" }, + { "R 0x18221ff8" }, + { "R 0x1822200c" }, + { "R 0x18222020" }, + { "R 0x18222034" }, + { "R 0x18222048" }, + { "R 0x1822205c" }, + { "R 0x18222070" }, + { "R 0x18222084" }, + { "R 0x18222098" }, + { "R 0x182220ac" }, + { "R 0x182220c0" }, + { "R 0x18221278" }, + { "R 0x1822128c" }, + { "R 0x182212a0" }, + { "R 0x182212b4" }, + { "R 0x182212c8" }, + { "R 0x182212dc" }, + { "R 0x182212f0" }, + { "R 0x18221304" }, + { "R 0x18221318" }, + { "R 0x1822132c" }, + { "R 0x18221340" }, + { "R 0x18221354" }, + { "R 0x18221368" }, + { "R 0x1822137c" }, + { "R 0x18221390" }, + { "R 0x182213a4" }, + { "R 0x18221518" }, + { "R 0x1822152c" }, + { "R 0x18221540" }, + { "R 0x18221554" }, + { "R 0x18221568" }, + { "R 0x1822157c" }, + { "R 0x18221590" }, + { "R 0x182215a4" }, + { "R 0x182215b8" }, + { "R 0x182215cc" }, + { "R 0x182215e0" }, + { "R 0x182215f4" }, + { "R 0x18221608" }, + { "R 0x1822161c" }, + { "R 0x18221630" }, + { "R 0x18221644" }, + { "R 0x182217b8" }, + { "R 0x182217cc" }, + { "R 0x182217e0" }, + { "R 0x182217f4" }, + { "R 0x18221808" }, + { "R 0x1822181c" }, + { "R 0x18221830" }, + { "R 0x18221844" }, + { "R 0x18221858" }, + { "R 0x1822186c" }, + { "R 0x18221880" }, + { "R 0x18221894" }, + { "R 0x182218a8" }, + { "R 0x182218bc" }, + { "R 0x182218d0" }, + { "R 0x182218e4" }, + { "R 0x18221a58" }, + { "R 0x18221a6c" }, + { "R 0x18221a80" }, + { "R 0x18221a94" }, + { "R 0x18221aa8" }, + { "R 0x18221abc" }, + { "R 0x18221ad0" }, + { "R 0x18221ae4" }, + { "R 0x18221af8" }, + { "R 0x18221b0c" }, + { "R 0x18221b20" }, + { "R 0x18221b34" }, + { "R 0x18221b48" }, + { "R 0x18221b5c" }, + { "R 0x18221b70" }, + { "R 0x18221b84" }, + { "R 0x18221cf8" }, + { "R 0x18221d0c" }, + { "R 0x18221d20" }, + { "R 0x18221d34" }, + { "R 0x18221d48" }, + { "R 0x18221d5c" }, + { "R 0x18221d70" }, + { "R 0x18221d84" }, + { "R 0x18221d98" }, + { "R 0x18221dac" }, + { "R 0x18221dc0" }, + { "R 0x18221dd4" }, + { "R 0x18221de8" }, + { "R 0x18221dfc" }, + { "R 0x18221e10" }, + { "R 0x18221e24" }, + { "R 0x18221f98" }, + { "R 0x18221fac" }, + { "R 0x18221fc0" }, + { "R 0x18221fd4" }, + { "R 0x18221fe8" }, + { "R 0x18221ffc" }, + { "R 0x18222010" }, + { "R 0x18222024" }, + { "R 0x18222038" }, + { "R 0x1822204c" }, + { "R 0x18222060" }, + { "R 0x18222074" }, + { "R 0x18222088" }, + { "R 0x1822209c" }, + { "R 0x182220b0" }, + { "R 0x182220c4" }, + { "R 0x18000024" }, + { "R 0x18000040" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x180800F8" }, + { "R 0x18080104" }, + { "R 0x1808011C" }, + { "R 0x18080128" }, + { "R 0x90b0280" }, + { "R 0x90b0288" }, + { "R 0x90b028c" }, + { "R 0x90b0290" }, + { "R 0x90b0294" }, + { "R 0x90b0298" }, + { "R 0x90b029c" }, + { "R 0x90b02a0" }, + { "R 0x18321700" }, + { "R 0x18322C18" }, + { "R 0x18323700" }, + { "R 0x18324C18" }, + { "R 0x18325F00" }, + { "R 0x18327418" }, + { "R 0x9236028" }, + { "R 0x923602C" }, + { "R 0x9236030" }, + { "R 0x9236034" }, + { "R 0x9236038" }, + { "R 0x9232100" }, + { "R 0x92360b0" }, + { "R 0x9236044" }, + { "R 0x9236048" }, + { "R 0x923604c" }, + { "R 0x9236050" }, + { "R 0x923e030" }, + { "R 0x923e034" }, + { "R 0x9241000" }, + { "R 0x9248058" }, + { "R 0x924805c" }, + { "R 0x9248060" }, + { "R 0x9248064" }, + { "R 0x9260410" }, + { "R 0x92e0410" }, + { "R 0x9260414" }, + { "R 0x92e0414" }, + { "R 0x9260418" }, + { "R 0x92e0418" }, + { "R 0x9260420" }, + { "R 0x9260424" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92e0420" }, + { "R 0x92e0424" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x9600000" }, + { "R 0x9601000" }, + { "R 0x9602000" }, + { "R 0x9603000" }, + { "R 0x9604000" }, + { "R 0x9605000" }, + { "R 0x9606000" }, + { "R 0x9607000" }, + { "R 0x9608000" }, + { "R 0x9609000" }, + { "R 0x960a000" }, + { "R 0x960b000" }, + { "R 0x960c000" }, + { "R 0x960d000" }, + { "R 0x960e000" }, + { "R 0x960f000" }, + { "R 0x9610000" }, + { "R 0x9611000" }, + { "R 0x9612000" }, + { "R 0x9613000" }, + { "R 0x9614000" }, + { "R 0x9615000" }, + { "R 0x9616000" }, + { "R 0x9617000" }, + { "R 0x9618000" }, + { "R 0x9619000" }, + { "R 0x961a000" }, + { "R 0x961b000" }, + { "R 0x961c000" }, + { "R 0x961d000" }, + { "R 0x961e000" }, + { "R 0x961f000" }, + { "R 0x9600004" }, + { "R 0x9601004" }, + { "R 0x9602004" }, + { "R 0x9603004" }, + { "R 0x9604004" }, + { "R 0x9605004" }, + { "R 0x9606004" }, + { "R 0x9607004" }, + { "R 0x9608004" }, + { "R 0x9609004" }, + { "R 0x960a004" }, + { "R 0x960b004" }, + { "R 0x960c004" }, + { "R 0x960d004" }, + { "R 0x960e004" }, + { "R 0x960f004" }, + { "R 0x9610004" }, + { "R 0x9611004" }, + { "R 0x9612004" }, + { "R 0x9613004" }, + { "R 0x9614004" }, + { "R 0x9615004" }, + { "R 0x9616004" }, + { "R 0x9617004" }, + { "R 0x9618004" }, + { "R 0x9619004" }, + { "R 0x961a004" }, + { "R 0x961b004" }, + { "R 0x961c004" }, + { "R 0x961d004" }, + { "R 0x961e004" }, + { "R 0x961f004" }, + { "R 0x9266418" }, + { "R 0x92e6418" }, + { "R 0x9265804" }, + { "R 0x92e5804" }, + { "R 0x92604b8" }, + { "R 0x92e04b8" }, + { "R 0x0C201244 1" }, + { "R 0x0C202244 1" }, + { "R 0x18100C18 1" }, + { "R 0x18101C18 1" }, + { "R 0x18300000 1" }, + { "R 0x183A3A84 2" }, + { "R 0x18393A84 2" }, + { "R 0x00100000" }, + { "R 0x00100004" }, + { "R 0x00100008" }, + { "R 0x0010000C" }, + { "R 0x00100010" }, + { "R 0x00100014" }, + { "R 0x00100018" }, + { "R 0x0010001C" }, + { "R 0x00100020" }, + { "R 0x00100024" }, + { "R 0x00100028" }, + { "R 0x0010002C" }, + { "R 0x00100030" }, + { "R 0x00100034" }, + { "R 0x00100100" }, + { "R 0x00100104" }, + { "R 0x00100108" }, + { "R 0x0010010C" }, + { "R 0x00101000" }, + { "R 0x00101004" }, + { "R 0x00101008" }, + { "R 0x0010100C" }, + { "R 0x00101010" }, + { "R 0x00101014" }, + { "R 0x00101018" }, + { "R 0x0010101C" }, + { "R 0x00101020" }, + { "R 0x00101024" }, + { "R 0x00101028" }, + { "R 0x0010102C" }, + { "R 0x00101030" }, + { "R 0x00101034" }, + { "R 0x00102000" }, + { "R 0x00102004" }, + { "R 0x00102008" }, + { "R 0x0010200C" }, + { "R 0x00102010" }, + { "R 0x00102014" }, + { "R 0x00102018" }, + { "R 0x0010201C" }, + { "R 0x00102020" }, + { "R 0x00102024" }, + { "R 0x00102028" }, + { "R 0x0010202C" }, + { "R 0x00102030" }, + { "R 0x00102034" }, + { "R 0x00103000" }, + { "R 0x00103004" }, + { "R 0x00103008" }, + { "R 0x0010300C" }, + { "R 0x00103010" }, + { "R 0x00103014" }, + { "R 0x00103018" }, + { "R 0x0010301C" }, + { "R 0x00103020" }, + { "R 0x00103024" }, + { "R 0x00103028" }, + { "R 0x0010302C" }, + { "R 0x00103030" }, + { "R 0x00103034" }, + { "R 0x00113000" }, + { "R 0x00113004" }, + { "R 0x00113008" }, + { "R 0x0011300C" }, + { "R 0x00113010" }, + { "R 0x00113014" }, + { "R 0x00113018" }, + { "R 0x0011301C" }, + { "R 0x00113020" }, + { "R 0x00113024" }, + { "R 0x00113028" }, + { "R 0x0011302C" }, + { "R 0x00113030" }, + { "R 0x00113034" }, + { "R 0x0011A000" }, + { "R 0x0011A004" }, + { "R 0x0011A008" }, + { "R 0x0011A00C" }, + { "R 0x0011A010" }, + { "R 0x0011A014" }, + { "R 0x0011A018" }, + { "R 0x0011A01C" }, + { "R 0x0011A020" }, + { "R 0x0011A024" }, + { "R 0x0011A028" }, + { "R 0x0011A02C" }, + { "R 0x0011A030" }, + { "R 0x0011A034" }, + { "R 0x0011B000" }, + { "R 0x0011B004" }, + { "R 0x0011B008" }, + { "R 0x0011B00C" }, + { "R 0x0011B010" }, + { "R 0x0011B014" }, + { "R 0x0011B018" }, + { "R 0x0011B01C" }, + { "R 0x0011B020" }, + { "R 0x0011B024" }, + { "R 0x0011B028" }, + { "R 0x0011B02C" }, + { "R 0x0011B030" }, + { "R 0x0011B034" }, + { "R 0x00174000" }, + { "R 0x00174004" }, + { "R 0x00174008" }, + { "R 0x0017400C" }, + { "R 0x00174010" }, + { "R 0x00174014" }, + { "R 0x00174018" }, + { "R 0x0017401C" }, + { "R 0x00174020" }, + { "R 0x00174024" }, + { "R 0x00174028" }, + { "R 0x0017402C" }, + { "R 0x00174030" }, + { "R 0x00174034" }, + { "R 0x00176000" }, + { "R 0x00176004" }, + { "R 0x00176008" }, + { "R 0x0017600C" }, + { "R 0x00176010" }, + { "R 0x00176014" }, + { "R 0x00176018" }, + { "R 0x0017601C" }, + { "R 0x00176020" }, + { "R 0x00176024" }, + { "R 0x00176028" }, + { "R 0x0017602C" }, + { "R 0x00176030" }, + { "R 0x00176034" }, + { "R 0x0010401C" }, + { "R 0x00183024" }, + { "R 0x00144168" }, + { "R 0x0011702C" }, + { "R 0x0010904C" }, + { "R 0x00189038" }, + { "R 0x001443E8" }, + { "R 0x001442B8" }, + { "R 0x00105060" }, + { "R 0x00141024" }, + { "R 0x00145038" }, + { "R 0x00109004" }, + { "R 0x00189004" }, + { "R 0x00190004" }, + { "R 0x0C2A0000" }, + { "R 0x0C2A0004" }, + { "R 0x0C2A0008" }, + { "R 0x0C2A000C" }, + { "R 0x0C2A0010" }, + { "R 0x0C2A0014" }, + { "R 0x0C2A0018" }, + { "R 0x0C2A001C" }, + { "R 0x0C2A0020" }, + { "R 0x0C2A0024" }, + { "R 0x0C2A0028" }, + { "R 0x0C2A002C" }, + { "R 0x0C2A0030" }, + { "R 0x0C2A0034" }, + { "R 0x0C2A1000" }, + { "R 0x0C2A1004" }, + { "R 0x0C2A1008" }, + { "R 0x0C2A100C" }, + { "R 0x0C2A1010" }, + { "R 0x0C2A1014" }, + { "R 0x0C2A1018" }, + { "R 0x0C2A101C" }, + { "R 0x0C2A1020" }, + { "R 0x0C2A1024" }, + { "R 0x0C2A1028" }, + { "R 0x0C2A102C" }, + { "R 0x0C2A1030" }, + { "R 0x0C2A2260" }, + { "R 0x0C2A2264" }, + { "R 0x0C2A3008" }, + { "R 0x0C2A300C" }, + { "R 0x0C2A3010" }, + { "R 0x0C2A3014" }, + { "R 0x0C2A3024" }, + { "R 0x0C2A2034" }, + { "R 0x0C2A214C" }, + { "R 0x0C2A2150" }, + { "R 0x0C2A2154" }, + { "R 0x0C2630A0 4" }, + { "R 0x0C2630B0 4" }, + { "R 0x0C2630C0 4" }, + { "R 0x0C2630D0 4" }, + { "R 0x1800005C 1" }, + { "R 0x1801005C 1" }, + { "R 0x1802005C 1" }, + { "R 0x1803005C 1" }, + { "R 0x1804005C 1" }, + { "R 0x1805005C 1" }, + { "R 0x1806005C 1" }, + { "R 0x1807005C 1" }, + { "R 0x3d96000" }, + { "R 0x3d96004" }, +}; + +static const struct dcc_link_config talos_link_configs[] = { + { + .link_list = 3, + .entries = talos_dcc_entries, + .num_entries = ARRAY_SIZE(talos_dcc_entries), + }, +}; + +static const struct dcc_config talos_config = { + .lists = talos_link_configs, + .num_lists = ARRAY_SIZE(talos_link_configs), +}; + +static const struct dcc_pdata talos_pdata = { + .base = 0x010a2000, + .size = 0x00001000, + .ram_base = 0x010ae000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x1, + .config = &talos_config, +}; + +#endif /* _QCOM_DCC_TALOS_CONFIG_H */ From 8e551dc5b09bad842190bc0605dca1d8c1c444fa Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 12:18:22 +0800 Subject: [PATCH 0023/1058] QCLINUX: qcom-dcc: group lemans and monaco SoC IDs with comments The lemans_pdata is shared by both Lemans (534, 667, 676) and Monaco (606, 674, 675) SoC variants. Add comments to distinguish the two groups and reorder the case labels accordingly. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 83efad89b4d76..3595200b37d7a 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -82,12 +82,14 @@ static int __init dcc_dev_init(void) goto fail; break; + /* lemans IDs */ case 534: - case 606: case 667: + case 676: + /* monaco IDs */ + case 606: case 674: case 675: - case 676: ret = platform_device_add_data(dcc_pdev, &lemans_pdata, sizeof(lemans_pdata)); if (ret) goto fail; From 275d5cadb9afc6daf1fe4d9cbf607dadb7f9afc8 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 13:56:57 +0800 Subject: [PATCH 0024/1058] QCLINUX: qcom-dcc: add kodiak register list and move config to header Add the full DCC register capture list for the Kodiak platform derived from debug_config_qcm6490.sh. The registers are distributed across three linked lists: - Link list 6: pcu, epss, pimem, core, gemnoc, tsens, spmi, gpu, sysnoc, aggrenoc, gcc (430 entries) - Link list 4: confignoc, limits, gic, mmssnoc, apps_rsc, misc, ddr (450 entries) - Link list 3: lpass_rsc, nsp_rsc, sdi_debug, lpass_cdsp_tunning, wpss_rsc, video_noc (231 entries) Estimated SRAM usage is ~14 KB, well within the 24 KB (0x6000) budget. Move the kodiak DCC configuration (entries arrays, link configs, dcc config, and pdata) into a dedicated header qcom-dcc-kodiak-config.h, consistent with the approach used for talos and lemans. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 10 +- drivers/misc/qcom-dcc-kodiak-config.h | 1188 +++++++++++++++++++++++++ 2 files changed, 1189 insertions(+), 9 deletions(-) create mode 100644 drivers/misc/qcom-dcc-kodiak-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 3595200b37d7a..cd8bad68a6077 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -9,20 +9,12 @@ #include "qcom-dcc.h" #include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" +#include "qcom-dcc-kodiak-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_pdata kodiak_pdata = { - .base = 0x0117f000, - .size = 0x00001000, - .ram_base = 0x01112000, - .ram_size = 0x00006000, - .dcc_offset = 0x12000, - .map_ver = 0x2, -}; - static const struct dcc_pdata pakala_pdata = { .base = 0x100ff000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-kodiak-config.h b/drivers/misc/qcom-dcc-kodiak-config.h new file mode 100644 index 0000000000000..7184252734917 --- /dev/null +++ b/drivers/misc/qcom-dcc-kodiak-config.h @@ -0,0 +1,1188 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_KODIAK_CONFIG_H +#define _QCOM_DCC_KODIAK_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry kodiak_dcc_entries_ll6[] = { + /* pcu */ + { "R 0x18000010" }, + { "R 0x18000024" }, + { "R 0x18000038 6" }, + { "R 0x18010010" }, + { "R 0x18010024" }, + { "R 0x18010038 6" }, + { "R 0x18020010" }, + { "R 0x18020024" }, + { "R 0x18020038 6" }, + { "R 0x18030010" }, + { "R 0x18030024" }, + { "R 0x18030038 6" }, + { "R 0x18040010" }, + { "R 0x18040024" }, + { "R 0x18040038 6" }, + { "R 0x18050010" }, + { "R 0x18050024" }, + { "R 0x18050038 6" }, + { "R 0x18060010" }, + { "R 0x18060024" }, + { "R 0x18060038 6" }, + { "R 0x18070010" }, + { "R 0x18070024" }, + { "R 0x18070038 6" }, + { "R 0x18080010" }, + { "R 0x18080024" }, + { "R 0x18080038 6" }, + { "R 0x1808006c 5" }, + { "R 0x18080084" }, + { "R 0x180800f4 18" }, + { "R 0x18080158 5" }, + { "R 0x18080170 2" }, + { "R 0x18080188 5" }, + { "R 0x180801ac 6" }, + { "R 0x180801c8" }, + { "R 0x180801f0" }, + /* epss */ + { "R 0x18598020" }, + { "R 0x1859001c 2" }, + { "R 0x1859002c" }, + { "R 0x18590064 6" }, + { "R 0x1859008c" }, + { "R 0x185900dc" }, + { "R 0x185900e8 3" }, + { "R 0x18590300" }, + { "R 0x1859030c" }, + { "R 0x18590320" }, + { "R 0x1859034c" }, + { "R 0x185903bc 2" }, + { "R 0x1859101c 2" }, + { "R 0x1859102c" }, + { "R 0x18591064 6" }, + { "R 0x1859108c" }, + { "R 0x185910dc" }, + { "R 0x185910e8 3" }, + { "R 0x18591300" }, + { "R 0x1859130c" }, + { "R 0x18591320" }, + { "R 0x1859134c" }, + { "R 0x185913bc 2" }, + { "R 0x1859201c 2" }, + { "R 0x1859202c" }, + { "R 0x18592064 6" }, + { "R 0x1859208c" }, + { "R 0x185920dc" }, + { "R 0x185920e8 3" }, + { "R 0x18592300" }, + { "R 0x1859230c" }, + { "R 0x18592320" }, + { "R 0x1859234c" }, + { "R 0x185923bc 2" }, + { "R 0x1859301c 2" }, + { "R 0x18593064 6" }, + { "R 0x1859308c" }, + { "R 0x185930dc" }, + { "R 0x185930e8 3" }, + { "R 0x18593300" }, + { "R 0x1859330c" }, + { "R 0x18593320" }, + { "R 0x1859302c" }, + { "R 0x1859334c" }, + { "R 0x185933bc 2" }, + { "R 0x18300000" }, + { "R 0x1830000c" }, + { "R 0x18300018" }, + { "R 0x17c21000 2" }, + { "R 0x18393a84 2" }, + { "R 0x183a3a84 2" }, + { "R 0x18280000 2" }, + { "R 0x18282000 2" }, + { "R 0x18284000 2" }, + { "R 0x18286000 2" }, + { "R 0x18300000" }, + { "R 0x18200400 3" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200d0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + /* pimem */ + { "R 0x610100 11" }, + /* core */ + { "R 0x18000058 4" }, + { "R 0x1800006c" }, + { "R 0x180000f0 2" }, + { "R 0x18010058 4" }, + { "R 0x1801006c" }, + { "R 0x180100f0 2" }, + { "R 0x18020058 4" }, + { "R 0x1802006c" }, + { "R 0x180200f0 2" }, + { "R 0x18030058 4" }, + { "R 0x1803006c" }, + { "R 0x180300f0 2" }, + { "R 0x18040058 4" }, + { "R 0x1804006c" }, + { "R 0x180400f0 2" }, + { "R 0x18050058 4" }, + { "R 0x1805006c" }, + { "R 0x180500f0 2" }, + { "R 0x18060058 4" }, + { "R 0x1806006c" }, + { "R 0x180600f0 2" }, + { "R 0x18070058 4" }, + { "R 0x1807006c" }, + { "R 0x180700f0 2" }, + { "R 0x18101908" }, + { "R 0x18101c18" }, + { "R 0x18390810" }, + { "R 0x18390c50" }, + { "R 0x18390814" }, + { "R 0x18390c54" }, + { "R 0x18390818" }, + { "R 0x18390c58" }, + { "R 0x18393a84 2" }, + { "R 0x18100908" }, + { "R 0x18100c18" }, + { "R 0x183a0810" }, + { "R 0x183a0c50" }, + { "R 0x183a0814" }, + { "R 0x183a0c54" }, + { "R 0x183a0818" }, + { "R 0x183a0c58" }, + { "R 0x183a3a84 2" }, + { "R 0x18393500" }, + { "R 0x18393580" }, + { "R 0x183a3500" }, + { "R 0x183a3580" }, + { "R 0x18282000 4" }, + { "R 0x18282028" }, + { "R 0x18282038" }, + { "R 0x18282080 5" }, + { "R 0x18286000 4" }, + { "R 0x18286028" }, + { "R 0x18286038" }, + { "R 0x18286080 5" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0x18300000" }, + { "R 0x1829208c" }, + { "R 0x18292098" }, + { "R 0x18292098" }, + { "R 0x1829608c" }, + { "R 0x18296098" }, + { "R 0x18296098" }, + { "R 0x784184" }, + /* gemnoc */ + { "R 0x9103008" }, + { "R 0x9103408" }, + { "R 0x9143008" }, + { "R 0x9143408" }, + { "R 0x91b0008" }, + { "R 0x91b1008" }, + { "R 0x9101808 2" }, + { "R 0x9141808 2" }, + { "R 0x91a8008 2" }, + { "R 0x91a8808 2" }, + { "R 0x9100000" }, + { "R 0x9100008 2" }, + { "R 0x9140000" }, + { "R 0x9140008 2" }, + { "R 0x9180000" }, + { "R 0x9180008 2" }, + { "R 0x9180404 3" }, + { "R 0x9181010" }, + { "R 0x9181020 8" }, + { "R 0x91e1048" }, + { "R 0x9121010" }, + { "R 0x9122010" }, + { "R 0x9123010" }, + { "R 0x9125010" }, + { "R 0x9161010" }, + { "R 0x9162010" }, + { "R 0x9163010" }, + { "R 0x9165010" }, + { "R 0x91cf010" }, + { "R 0x91d0010" }, + { "R 0x91d1010" }, + { "R 0x91d2010" }, + { "R 0x91d3010" }, + { "R 0x91d4010" }, + { "R 0x91d5010" }, + { "R 0x91d6010" }, + { "R 0x91d7010" }, + { "R 0x9101408" }, + { "R 0x9141410" }, + { "R 0x9100810" }, + { "R 0x9140810" }, + { "R 0x9100820" }, + { "R 0x9140820" }, + { "R 0x9100828 2" }, + { "R 0x9140828 2" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + /* spmi */ + { "R 0xc410000" }, + { "R 0xc40af04" }, + { "R 0xc40af10" }, + { "R 0xc40a000" }, + { "R 0xc40a018" }, + { "R 0xc40a028 2" }, + { "R 0xc40a100" }, + { "R 0xc2a22fc 3" }, + { "R 0xc440200 2" }, + { "R 0xc442200 4" }, + /* gpu */ + { "R 0x3d9100c 3" }, + { "R 0x3d9106c 3" }, + { "R 0x3d91004" }, + { "R 0x3d91054 5" }, + { "R 0x3d91070 2" }, + { "R 0x3d91080 3" }, + { "R 0x3d91078 2" }, + { "R 0x3d9108c 2" }, + { "R 0x3d91098 2" }, + { "R 0x3d910a4 2" }, + { "R 0x3d910f0 2" }, + { "R 0x3d91100" }, + { "R 0x3d91118" }, + { "R 0x3d91164 2" }, + { "R 0x3d91170" }, + { "R 0x3d91178" }, + { "R 0x3d91204" }, + { "R 0x3d9120c" }, + { "R 0x3d98024" }, + { "R 0x3d9802c 2" }, + { "R 0x3d92000 2" }, + { "R 0x3d93000 2" }, + { "R 0x3d95000 2" }, + { "R 0x3d96000 2" }, + { "R 0x3d97000 2" }, + { "R 0x119000" }, + { "R 0x11903c" }, + { "R 0x171004 3" }, + { "R 0x171014 2" }, + { "R 0x171154 3" }, + { "R 0x17a04c" }, + { "R 0x17b000" }, + { "R 0x17b03c" }, + { "R 0x17c000" }, + { "R 0x17c03c" }, + { "R 0x17d000" }, + { "R 0x17d03c" }, + { "R 0x17e000" }, + { "R 0x17e03c" }, + { "R 0x187000" }, + { "R 0x18703c" }, + { "R 0x3d91534" }, + { "R 0x3d002b4" }, + { "R 0x3d00410 2" }, + { "R 0x3d00818" }, + { "R 0x3d7e220 2" }, + /* sysnoc */ + { "R 0x1680000" }, + { "R 0x1680008" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1680248" }, + { "R 0x1680b00 6" }, + /* aggrenoc */ + { "R 0x16e4008" }, + { "R 0x1706208" }, + { "R 0x16e0000" }, + { "R 0x16e0010" }, + { "R 0x16e0008" }, + { "R 0x16e0020 8" }, + { "R 0x16e5048" }, + { "R 0x16e5248" }, + { "R 0x16e5448" }, + { "R 0x16e5100 5" }, + { "R 0x16e5300 2" }, + { "R 0x16e5500 2" }, + { "R 0x1700000" }, + { "R 0x1700008" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x170b100 5" }, + { "R 0x170b048" }, + /* gcc */ + { "R 0x100000 15" }, + { "R 0x101000 15" }, + { "R 0x176000 15" }, + { "R 0x174000 15" }, + { "R 0x113000 15" }, + { "R 0x11a000 15" }, + { "R 0x11c000 15" }, + { "R 0x11c048 3" }, + { "R 0x11e000 15" }, + { "R 0x10401c" }, + { "R 0x105074" }, + { "R 0x183024" }, + { "R 0x109050" }, + { "R 0x123020" }, + { "R 0x117024" }, + { "R 0x117154" }, + { "R 0x117284" }, + { "R 0x1173b4" }, + { "R 0x1174e4" }, + { "R 0x117614" }, + { "R 0x117744" }, + { "R 0x117874" }, + { "R 0x118024" }, + { "R 0x118154" }, + { "R 0x118284" }, + { "R 0x1183b4" }, + { "R 0x1184e4" }, + { "R 0x118614" }, + { "R 0x118744" }, + { "R 0x118874" }, + { "R 0x129020" }, + { "R 0x11d020" }, + { "R 0x134024" }, + { "R 0x141024" }, + { "R 0x14415c" }, + { "R 0x14504c" }, + { "R 0x18903c" }, + { "R 0x151000" }, + { "R 0x151008" }, + { "R 0x151010" }, + { "R 0x152000" }, + { "R 0x152008" }, + { "R 0x152010" }, + { "R 0x153020" }, + { "R 0x153028" }, + { "R 0x153030" }, + { "R 0x155000" }, + { "R 0x155008" }, + { "R 0x155010" }, + { "R 0x15b000" }, + { "R 0x15b008" }, + { "R 0x15b010" }, + { "R 0x157000" }, + { "R 0x157008" }, + { "R 0x157010" }, + { "R 0x135020" }, + { "R 0x135028" }, + { "R 0x135030" }, + { "R 0x156000" }, + { "R 0x156008" }, + { "R 0x156010" }, + { "R 0x15a000" }, + { "R 0x15a008" }, + { "R 0x15a010" }, + { "R 0x190004" }, + { "R 0x109008" }, + { "R 0x190010" }, + { "R 0x190020" }, + { "R 0x190028" }, + { "R 0x109010" }, + { "R 0x109018" }, + { "R 0x109018" }, + { "R 0x109020" }, + { "R 0x18d080" }, + { "R 0x145014" }, + { "R 0x14501c" }, + { "R 0x183004 2" }, + { "R 0x183140" }, + { "R 0x171158 2" }, + { "R 0x109004 3" }, + { "R 0x109160" }, + { "R 0x109468" }, + { "R 0x10f004 3" }, + { "R 0x145000 3" }, + { "R 0x16b004 3" }, + { "R 0x18d004 3" }, + { "R 0x177004 3" }, + { "R 0x189004 3" }, + { "R 0x153000 9" }, + { "R 0x135000 9" }, + { "R 0x106100" }, + { "R 0x147004" }, + { "R 0x17b000 12" }, + { "R 0x17b03c 12" }, + { "R 0x17c000 12" }, + { "R 0x17c03c 12" }, + { "R 0x153124" }, + { "R 0x156124" }, + { "R 0x1453a4" }, + { "R 0x182884" }, + { "R 0x145384" }, + { "R 0xc2a0000 15" }, + { "R 0xc2a1000 15" }, + { "R 0x17101c 2" }, + { "R 0x14401c 2" }, + { "R 0x183010 2" }, + { "R 0x18a160 2" }, + { "R 0x18a004" }, + { "R 0x18a01c 3" }, + { "R 0x19d004 2" }, + { "R 0x196100" }, + { "R 0x10003c" }, + { "R 0x10103c" }, + { "R 0x10203c" }, + { "R 0x10303c" }, + { "R 0x11303c" }, + { "R 0x11a03c" }, + { "R 0x11c03c" }, + { "R 0x17403c" }, + { "R 0x17603c" }, + { "R 0x11e03c" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll4[] = { + /* confignoc */ + { "R 0x1510008" }, + { "R 0x151d208" }, + { "R 0x1507008" }, + { "R 0x151d308" }, + { "R 0x1509008" }, + { "R 0x1514008" }, + { "R 0x1500000" }, + { "R 0x1500010" }, + { "R 0x1510010" }, + { "R 0x1500020 8" }, + { "R 0x1510020 8" }, + { "R 0x1511048" }, + { "R 0x1501048 2" }, + { "R 0x1501058" }, + { "R 0x1501248" }, + { "R 0x1511248" }, + { "R 0x1501248" }, + { "R 0x1511b00" }, + { "R 0x151e100" }, + { "R 0x150b100" }, + /* limits */ + { "R 0xec80004" }, + { "R 0xec80058" }, + { "R 0xec80060 8" }, + { "R 0xec800a0 40" }, + { "R 0x634008" }, + { "R 0x634f00 8" }, + { "R 0x635560" }, + { "R 0x635570" }, + { "R 0x635580" }, + { "R 0x635590" }, + { "R 0x6355a0 4" }, + { "R 0x635600" }, + { "R 0x635610" }, + { "R 0x636008" }, + { "R 0x636f00 8" }, + { "R 0x637560" }, + { "R 0x637570" }, + { "R 0x637580" }, + { "R 0x637590" }, + { "R 0x6375a0 4" }, + { "R 0x637600" }, + { "R 0x637610" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d10 12" }, + { "R 0x18370f90 10" }, + { "R 0x18371010 10" }, + { "R 0x18371a10 8" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d10 8" }, + { "R 0x18378f90 6" }, + { "R 0x18379010 6" }, + { "R 0x18379a10 4" }, + { "R 0xa310220 3" }, + { "R 0xa3102a0 3" }, + { "R 0xa3104a0 6" }, + { "R 0xa310520" }, + { "R 0xa310588" }, + { "R 0xa310d10 8" }, + { "R 0xa310f90 6" }, + { "R 0xa311010 6" }, + { "R 0xa311a10 3" }, + /* gic */ + { "R 0x17a00104 29" }, + { "R 0x17a00204 29" }, + /* mmssnoc */ + { "R 0x1741008" }, + { "R 0x1740000" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020 8" }, + { "R 0x174b048" }, + { "R 0x174b100 8" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x1750010" }, + { "R 0x1750190" }, + { "R 0x1751010" }, + { "R 0x1752010" }, + { "R 0x1754010" }, + { "R 0x1755010" }, + { "R 0x1756010" }, + { "R 0x1758010" }, + { "R 0x1758090" }, + { "R 0x1759010" }, + { "R 0x175a010" }, + { "R 0x175c010" }, + { "R 0x175d010" }, + { "R 0x175e010" }, + /* apps_rsc */ + { "R 0xb201020 2" }, + { "R 0xb200010 4" }, + { "R 0xb220010 4" }, + { "R 0xb200900 4" }, + { "R 0xb220900 4" }, + { "R 0xb201030" }, + { "R 0xb201204" }, + { "R 0xb201218" }, + { "R 0xb20122c" }, + { "R 0xb201240" }, + { "R 0xb201254" }, + { "R 0xb201208" }, + { "R 0xb20121c" }, + { "R 0xb201230" }, + { "R 0xb201244" }, + { "R 0xb201258" }, + { "R 0xb204510 2" }, + { "R 0xb204520" }, + { "R 0xb211024" }, + { "R 0xb221024" }, + { "R 0xb231024" }, + { "R 0x18220010" }, + { "R 0x18220030" }, + { "R 0x182200d0" }, + { "R 0x18220408" }, + { "R 0x18230408" }, + /* misc */ + { "R 0x17e00434" }, + { "R 0x17e0043c 2" }, + { "R 0x17c00038 2" }, + { "R 0x17c00438" }, + { "R 0x17e0041c 2" }, + { "R 0x17e00404" }, + { "R 0xc220000 2" }, + { "R 0xc230000 6" }, + { "R 0xc260008" }, + { "R 0x18598014" }, + { "R 0x4d8634" }, + { "R 0x4d8834" }, + { "R 0x418620" }, + { "R 0x418820" }, + /* ddr */ + { "R 0x9084208" }, + { "R 0x9084204" }, + { "R 0x9084108" }, + { "R 0x90841c0" }, + { "R 0x10c034 2" }, + { "R 0x144018" }, + { "R 0x9050078" }, + { "R 0x9050110 8" }, + { "R 0x9080058 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800fc" }, + { "R 0x9084030" }, + { "R 0x9084038 2" }, + { "R 0x90840e4" }, + { "R 0x90840f4" }, + { "R 0x9084104 2" }, + { "R 0x9084198" }, + { "R 0x9084804" }, + { "R 0x908480c" }, + { "R 0x9084844" }, + { "R 0x9084850 2" }, + { "R 0x9084860 3" }, + { "R 0x9084888 2" }, + { "R 0x908409c 2" }, + { "R 0x908426c" }, + { "R 0x908439c" }, + { "R 0x9085124" }, + { "R 0x9085134 2" }, + { "R 0x9084840" }, + { "R 0x9084834" }, + { "R 0x9085124" }, + { "R 0x90ba280" }, + { "R 0x90ba288 7" }, + { "R 0x9258610 4" }, + { "R 0x92d8610 4" }, + { "R 0x9220344 8" }, + { "R 0x9220370 6" }, + { "R 0x9220480" }, + { "R 0x9222400" }, + { "R 0x922240c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 3" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x9232100" }, + { "R 0x9236040 6" }, + { "R 0x92360b0" }, + { "R 0x923a004 4" }, + { "R 0x923e030 2" }, + { "R 0x9241000" }, + { "R 0x9242028" }, + { "R 0x9242044 3" }, + { "R 0x9242070" }, + { "R 0x9248030" }, + { "R 0x9248048 8" }, + { "R 0x9238030" }, + { "R 0x9238060 2" }, + { "R 0x9238074" }, + { "R 0x9238088" }, + { "R 0x92380a0" }, + { "R 0x92380b0" }, + { "R 0x92a0344 8" }, + { "R 0x92a0370 6" }, + { "R 0x92a0480" }, + { "R 0x92a2400" }, + { "R 0x92a240c" }, + { "R 0x92a3214 2" }, + { "R 0x92a3220 3" }, + { "R 0x92a3308" }, + { "R 0x92a3318" }, + { "R 0x92b2100" }, + { "R 0x92b6040 6" }, + { "R 0x92b60b0" }, + { "R 0x92ba004 4" }, + { "R 0x92be030 2" }, + { "R 0x92c1000" }, + { "R 0x92c2028" }, + { "R 0x92c2044 3" }, + { "R 0x92c2070" }, + { "R 0x92c8030" }, + { "R 0x92c8048 8" }, + { "R 0x92b8030" }, + { "R 0x92b8060 2" }, + { "R 0x92b8074" }, + { "R 0x92b8088" }, + { "R 0x92b80a0" }, + { "R 0x92b80b0" }, + { "R 0x92c8064" }, + { "R 0x9270080" }, + { "R 0x9270310" }, + { "R 0x9270400" }, + { "R 0x9270410 6" }, + { "R 0x9270430" }, + { "R 0x9270440" }, + { "R 0x9270448" }, + { "R 0x92704a0" }, + { "R 0x92704b0" }, + { "R 0x92704b8 2" }, + { "R 0x92704d0 2" }, + { "R 0x9271400" }, + { "R 0x9271408" }, + { "R 0x927341c 2" }, + { "R 0x92753b0" }, + { "R 0x9275804" }, + { "R 0x9275c18 2" }, + { "R 0x9275c2c" }, + { "R 0x9275c38" }, + { "R 0x9276418 2" }, + { "R 0x9279100" }, + { "R 0x9279110" }, + { "R 0x9279120" }, + { "R 0x9279180 2" }, + { "R 0x92f0080" }, + { "R 0x92f0310" }, + { "R 0x92f0400" }, + { "R 0x92f0410 6" }, + { "R 0x92f0430" }, + { "R 0x92f0440" }, + { "R 0x92f0448" }, + { "R 0x92f04a0" }, + { "R 0x92f04b0" }, + { "R 0x92f04b8 2" }, + { "R 0x92f04d0 2" }, + { "R 0x92f1400" }, + { "R 0x92f1408" }, + { "R 0x92f341c 2" }, + { "R 0x92f53b0" }, + { "R 0x92f5804" }, + { "R 0x92f5c18 2" }, + { "R 0x92f5c2c" }, + { "R 0x92f5c38" }, + { "R 0x92f6418 2" }, + { "R 0x92f9100" }, + { "R 0x92f9110" }, + { "R 0x92f9120" }, + { "R 0x92f9180 2" }, + { "R 0x9260080" }, + { "R 0x9260400" }, + { "R 0x9260410 3" }, + { "R 0x9260420 2" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92604b0" }, + { "R 0x92604b8 2" }, + { "R 0x92604d0 2" }, + { "R 0x9261400" }, + { "R 0x9263410" }, + { "R 0x92653b0" }, + { "R 0x9265804" }, + { "R 0x9265b1c" }, + { "R 0x9265b2c" }, + { "R 0x9265b38" }, + { "R 0x9269100" }, + { "R 0x9269108" }, + { "R 0x9269110" }, + { "R 0x9269118" }, + { "R 0x9269120" }, + { "R 0x9269180 2" }, + { "R 0x92e0080" }, + { "R 0x92e0400" }, + { "R 0x92e0410 3" }, + { "R 0x92e0420 2" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x92e04b0" }, + { "R 0x92e04b8 2" }, + { "R 0x92e04d0 2" }, + { "R 0x92e1400" }, + { "R 0x92e3410" }, + { "R 0x92e53b0" }, + { "R 0x92e5804" }, + { "R 0x92e5b1c" }, + { "R 0x92e5b2c" }, + { "R 0x92e5b38" }, + { "R 0x92e9100" }, + { "R 0x92e9108" }, + { "R 0x92e9110" }, + { "R 0x92e9118" }, + { "R 0x92e9120" }, + { "R 0x92e9180 2" }, + { "R 0x96b0868" }, + { "R 0x96b0870" }, + { "R 0x96b1004" }, + { "R 0x96b100c" }, + { "R 0x96b1014" }, + { "R 0x96b1204" }, + { "R 0x96b120c" }, + { "R 0x96b1214" }, + { "R 0x96b1504" }, + { "R 0x96b150c" }, + { "R 0x96b1514" }, + { "R 0x96b1604" }, + { "R 0x96b8100" }, + { "R 0x96b813c" }, + { "R 0x96b8500" }, + { "R 0x96b853c" }, + { "R 0x96b8a04" }, + { "R 0x96b8a18" }, + { "R 0x96b8ea8" }, + { "R 0x96b9044" }, + { "R 0x96b904c" }, + { "R 0x96b9054" }, + { "R 0x96b905c" }, + { "R 0x96b910c 2" }, + { "R 0x96b9204" }, + { "R 0x96b920c" }, + { "R 0x96b9238" }, + { "R 0x96b9240" }, + { "R 0x96b926c" }, + { "R 0x96b9394" }, + { "R 0x96b939c" }, + { "R 0x96b9704" }, + { "R 0x96b970c" }, + { "R 0x96f0868" }, + { "R 0x96f0870" }, + { "R 0x96f1004" }, + { "R 0x96f100c" }, + { "R 0x96f1014" }, + { "R 0x96f1204" }, + { "R 0x96f120c" }, + { "R 0x96f1214" }, + { "R 0x96f1504" }, + { "R 0x96f150c" }, + { "R 0x96f1514" }, + { "R 0x96f1604" }, + { "R 0x96f8100" }, + { "R 0x96f813c" }, + { "R 0x96f8500" }, + { "R 0x96f853c" }, + { "R 0x96f8a04" }, + { "R 0x96f8a18" }, + { "R 0x96f8ea8" }, + { "R 0x96f9044" }, + { "R 0x96f904c" }, + { "R 0x96f9054" }, + { "R 0x96f905c" }, + { "R 0x96f910c 2" }, + { "R 0x96f9204" }, + { "R 0x96f920c" }, + { "R 0x96f9238" }, + { "R 0x96f9240" }, + { "R 0x96f926c" }, + { "R 0x96f9394" }, + { "R 0x96f939c" }, + { "R 0x96f9704" }, + { "R 0x96f970c" }, + { "R 0x9130100 3" }, + { "R 0x9170100 3" }, + { "R 0x91dd100 4" }, + { "R 0x91df100" }, + { "R 0x610110 5" }, + { "R 0x9230010" }, + { "R 0x9230020" }, + { "R 0x9230030" }, + { "R 0x9230040" }, + { "R 0x92b0010" }, + { "R 0x92b0020" }, + { "R 0x92b0030" }, + { "R 0x92b0040" }, + { "R 0x9232050" }, + { "R 0x923605c 2" }, + { "R 0x92360a0" }, + { "R 0x923a018 2" }, + { "R 0x92b2050" }, + { "R 0x92b605c 2" }, + { "R 0x92b60a0" }, + { "R 0x92ba018 2" }, + { "R 0x9222404 2" }, + { "R 0x9222410" }, + { "R 0x9238004" }, + { "R 0x9238014" }, + { "R 0x923805c" }, + { "R 0x923a014" }, + { "R 0x92a2404 2" }, + { "R 0x92a2410" }, + { "R 0x92b8004" }, + { "R 0x92b8014" }, + { "R 0x92b805c" }, + { "R 0x92ba014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x9067e00 124" }, + { "R 0x905000c" }, + { "R 0x9050948" }, + { "R 0x9050078" }, + { "R 0x9050008" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll3[] = { + /* lpass_rsc */ + { "R 0xb254520" }, + { "R 0xb251020 2" }, + { "R 0xb251030" }, + { "R 0xb251200" }, + { "R 0xb251214" }, + { "R 0xb251228" }, + { "R 0xb25123c" }, + { "R 0xb251250" }, + { "R 0xb251204" }, + { "R 0xb251218" }, + { "R 0xb25122c" }, + { "R 0xb251240" }, + { "R 0xb251254" }, + { "R 0xb251208" }, + { "R 0xb25121c" }, + { "R 0xb251230" }, + { "R 0xb251244" }, + { "R 0xb251258" }, + { "R 0xb254510 2" }, + { "R 0xb250010 2" }, + { "R 0xb250900 2" }, + { "R 0x3500010 3" }, + { "R 0x3500030" }, + { "R 0x3500038" }, + { "R 0x3500040" }, + { "R 0x3500048" }, + { "R 0x35000d0" }, + { "R 0x3500210" }, + { "R 0x3500230" }, + { "R 0x3500250" }, + { "R 0x3500270" }, + { "R 0x3500290" }, + { "R 0x35002b0" }, + { "R 0x3500208" }, + { "R 0x3500228" }, + { "R 0x3500248" }, + { "R 0x3500268" }, + { "R 0x3500288" }, + { "R 0x35002a8" }, + { "R 0x350020c" }, + { "R 0x350022c" }, + { "R 0x350024c" }, + { "R 0x350026c" }, + { "R 0x350028c" }, + { "R 0x35002ac" }, + { "R 0x3500400 3" }, + { "R 0x3500d04" }, + { "R 0x30b0010 3" }, + { "R 0x30b0210" }, + { "R 0x30b0230" }, + { "R 0x30b0250" }, + { "R 0x30b0270" }, + { "R 0x30b0290" }, + { "R 0x30b02b0" }, + { "R 0x30b0208" }, + { "R 0x30b0228" }, + { "R 0x30b0248" }, + { "R 0x30b0268" }, + { "R 0x30b0288" }, + { "R 0x30b02a8" }, + { "R 0x30b020c" }, + { "R 0x30b022c" }, + { "R 0x30b024c" }, + { "R 0x30b026c" }, + { "R 0x30b028c" }, + { "R 0x30b02ac" }, + { "R 0x30b0400 3" }, + /* nsp_rsc */ + { "R 0xb2b4520" }, + { "R 0xb2b1020 2" }, + { "R 0xb2b1030" }, + { "R 0xb2b1200" }, + { "R 0xb2b1214" }, + { "R 0xb2b1228" }, + { "R 0xb2b123c" }, + { "R 0xb2b1250" }, + { "R 0xb2b1204" }, + { "R 0xb2b1218" }, + { "R 0xb2b122c" }, + { "R 0xb2b1240" }, + { "R 0xb2b1254" }, + { "R 0xb2b1208" }, + { "R 0xb2b121c" }, + { "R 0xb2b1230" }, + { "R 0xb2b1244" }, + { "R 0xb2b1258" }, + { "R 0xb2b4510 2" }, + { "R 0xb2b0010" }, + { "R 0xb2b0900" }, + { "R 0xa302028" }, + { "R 0xa0a4010 3" }, + { "R 0xa0a4030" }, + { "R 0xa0a4038" }, + { "R 0xa0a4040 2" }, + { "R 0xa0a40d0" }, + { "R 0xa0a4210" }, + { "R 0xa0a4230" }, + { "R 0xa0a4250" }, + { "R 0xa0a4270" }, + { "R 0xa0a4290" }, + { "R 0xa0a42b0" }, + { "R 0xa0a4208" }, + { "R 0xa0a4228" }, + { "R 0xa0a4248" }, + { "R 0xa0a4268" }, + { "R 0xa0a4288" }, + { "R 0xa0a42a8" }, + { "R 0xa0a420c" }, + { "R 0xa0a422c" }, + { "R 0xa0a424c" }, + { "R 0xa0a426c" }, + { "R 0xa0a428c" }, + { "R 0xa0a42ac" }, + { "R 0xa0a4400 2" }, + { "R 0xa0a4d04" }, + { "R 0xa3b0010 3" }, + { "R 0xa3b0210" }, + { "R 0xa3b0230" }, + { "R 0xa3b0250" }, + { "R 0xa3b0270" }, + { "R 0xa3b0290" }, + { "R 0xa3b02b0" }, + { "R 0xa3b0208" }, + { "R 0xa3b0228" }, + { "R 0xa3b0248" }, + { "R 0xa3b0268" }, + { "R 0xa3b0288" }, + { "R 0xa3b02a8" }, + { "R 0xa3b020c" }, + { "R 0xa3b022c" }, + { "R 0xa3b024c" }, + { "R 0xa3b026c" }, + { "R 0xa3b028c" }, + { "R 0xa3b02ac" }, + { "R 0xa3b0400 3" }, + /* sdi_debug */ + { "R 0x10413c" }, + { "R 0x105024" }, + { "R 0x108008" }, + { "R 0x108004" }, + { "R 0x10500c" }, + { "R 0x105658" }, + { "R 0x105640 2" }, + { "R 0x105010" }, + { "R 0x10500c" }, + { "R 0x105024" }, + /* lpass_cdsp_tunning */ + { "R 0x3500d00 3" }, + { "R 0x3500d10 4" }, + { "R 0x3500fb0 4" }, + { "R 0x3501250 4" }, + { "R 0x35014f0 4" }, + { "R 0x3501790 4" }, + { "R 0x3501a30 4" }, + { "R 0x3503d44 4" }, + { "R 0x35000d0 3" }, + { "R 0x3500100" }, + { "R 0x3500d3c" }, + { "R 0xa0a40d0 3" }, + { "R 0xa0a4100" }, + { "R 0xa0a4d3c" }, + { "R 0xa0a7d44 4" }, + { "R 0xa0a4d00 3" }, + /* wpss_rsc */ + { "R 0x8a02028" }, + { "R 0x8b00000 2" }, + { "R 0x8b00010 15" }, + { "R 0x8b000d0" }, + { "R 0x8b000d8" }, + { "R 0x8b00100 3" }, + { "R 0x8b00200 2" }, + { "R 0x8b00224" }, + { "R 0x8b00244" }, + { "R 0x8b00264" }, + { "R 0x8b00284" }, + { "R 0x8b002a4" }, + { "R 0x8b00208" }, + { "R 0x8b00228" }, + { "R 0x8b00248" }, + { "R 0x8b00268" }, + { "R 0x8b00288" }, + { "R 0x8b002a8" }, + { "R 0x8b0020c" }, + { "R 0x8b0022c" }, + { "R 0x8b0024c" }, + { "R 0x8b0026c" }, + { "R 0x8b0028c" }, + { "R 0x8b002ac" }, + { "R 0x8b00210" }, + { "R 0x8b00230" }, + { "R 0x8b00250" }, + { "R 0x8b00270" }, + { "R 0x8b00290" }, + { "R 0x8b002b0" }, + { "R 0x8b00400 3" }, + { "R 0x8b00460 2" }, + { "R 0x8b004a0 7" }, + { "R 0x8ab0000 2" }, + { "R 0x8ab0010 3" }, + { "R 0x8ab00d0" }, + { "R 0x8ab00d8" }, + { "R 0x8ab0100 3" }, + { "R 0x8ab0200 2" }, + { "R 0x8ab0224" }, + { "R 0x8ab0244" }, + { "R 0x8ab0264" }, + { "R 0x8ab0284" }, + { "R 0x8ab02a4" }, + { "R 0x8ab0208" }, + { "R 0x8ab0228" }, + { "R 0x8ab0248" }, + { "R 0x8ab0268" }, + { "R 0x8ab0288" }, + { "R 0x8ab02a8" }, + { "R 0x8ab020c" }, + { "R 0x8ab022c" }, + { "R 0x8ab024c" }, + { "R 0x8ab026c" }, + { "R 0x8ab028c" }, + { "R 0x8ab02ac" }, + { "R 0x8ab0210" }, + { "R 0x8ab0230" }, + { "R 0x8ab0250" }, + { "R 0x8ab0270" }, + { "R 0x8ab0290" }, + { "R 0x8ab02b0" }, + { "R 0x8ab0400 3" }, + { "R 0x8ab0460 2" }, + { "R 0x8ab04a0 7" }, + /* video_noc */ + { "R 0xaa10504 2" }, + { "R 0xaa10510" }, + { "R 0xaa10520 8" }, + { "R 0xaa10300" }, + { "R 0xaa10010" }, + { "R 0xaa10020" }, +}; + +static const struct dcc_link_config kodiak_link_configs[] = { + { + .link_list = 6, + .entries = kodiak_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = kodiak_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll4), + }, + { + .link_list = 3, + .entries = kodiak_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll3), + }, +}; + +static const struct dcc_config kodiak_config = { + .lists = kodiak_link_configs, + .num_lists = ARRAY_SIZE(kodiak_link_configs), +}; + +static const struct dcc_pdata kodiak_pdata = { + .base = 0x0117f000, + .size = 0x00001000, + .ram_base = 0x01112000, + .ram_size = 0x00006000, + .dcc_offset = 0x12000, + .map_ver = 0x2, + .config = &kodiak_config, +}; + +#endif /* _QCOM_DCC_KODIAK_CONFIG_H */ From 53e8e4b953a1812f7460d3d0bbec56eb62d091e3 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 14:12:34 +0800 Subject: [PATCH 0025/1058] QCLINUX: qcom-dcc: add pakala register list and move config to header Add the DCC register capture list for the Pakala platform. The registers are distributed across two linked lists: - Link list 6: 910 entries - Link list 4: 212 entries Estimated SRAM usage is ~15 KB, within the 16 KB (0x4000) budget. Move the pakala DCC configuration (entries arrays, link configs, dcc config, and pdata) into a dedicated header qcom-dcc-pakala-config.h, consistent with the approach used for other platforms. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 10 +- drivers/misc/qcom-dcc-pakala-config.h | 1167 +++++++++++++++++++++++++ 2 files changed, 1168 insertions(+), 9 deletions(-) create mode 100644 drivers/misc/qcom-dcc-pakala-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index cd8bad68a6077..a77b5bc144982 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -10,20 +10,12 @@ #include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" #include "qcom-dcc-kodiak-config.h" +#include "qcom-dcc-pakala-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_pdata pakala_pdata = { - .base = 0x100ff000, - .size = 0x00001000, - .ram_base = 0x10084000, - .ram_size = 0x4000, - .dcc_offset = 0x4000, - .map_ver = 0x3, -}; - static const struct dcc_pdata kaanapali_pdata = { .base = 0x100ff000, .size = 0x1000, diff --git a/drivers/misc/qcom-dcc-pakala-config.h b/drivers/misc/qcom-dcc-pakala-config.h new file mode 100644 index 0000000000000..25e6221805d27 --- /dev/null +++ b/drivers/misc/qcom-dcc-pakala-config.h @@ -0,0 +1,1167 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_PAKALA_CONFIG_H +#define _QCOM_DCC_PAKALA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry pakala_dcc_entries_ll6[] = { + { "R 0x16801000 2" }, + { "R 0x18880258 10" }, + { "R 0x18880288 6" }, + { "R 0x188802a8 10" }, + { "R 0x18880328 6" }, + { "R 0x188803d8 10" }, + { "R 0x18880408 2" }, + { "R 0x19880258 10" }, + { "R 0x19880288 6" }, + { "R 0x198802a8 10" }, + { "R 0x19880328 6" }, + { "R 0x198803d8 10" }, + { "R 0x19880408 2" }, + { "R 0x188b0000 4" }, + { "R 0x188b0050 2" }, + { "R 0x188b00e8 36" }, + { "R 0x188b0788 2" }, + { "R 0x188b0c18 2" }, + { "R 0x198b0000 4" }, + { "R 0x198b0050 2" }, + { "R 0x198b00e8 36" }, + { "R 0x198b0788 2" }, + { "R 0x198b0c18 2" }, + { "R 0x17988814 2" }, + { "R 0x17998814 2" }, + { "R 0x179d2000 3" }, + { "R 0x179d2020 3" }, + { "R 0x179d2040 2" }, + { "R 0x179d2060 2" }, + { "R 0x179d2080 2" }, + { "R 0x179d20a0" }, + { "R 0x179d20b0" }, + { "R 0x179d20c0" }, + { "R 0x179d2200 2" }, + { "R 0x179d2220 2" }, + { "R 0x179d2280 2" }, + { "R 0x179d22f0" }, + { "R 0x179d2304" }, + { "R 0x179d2310" }, + { "R 0x179d2400 4" }, + { "R 0x179d2420" }, + { "R 0x179d2428 2" }, + { "R 0x179d2440 2" }, + { "R 0x179d2520 2" }, + { "R 0x179d2600 2" }, + { "R 0x179d2710 2" }, + { "R 0x179d2720 2" }, + { "R 0x179d2740 2" }, + { "R 0x179d3080 2" }, + { "R 0x17846018 2" }, + { "R 0x17846060" }, + { "R 0x17846100 2" }, + { "R 0x17846110" }, + { "R 0x17847030 2" }, + { "R 0x17847040 2" }, + { "R 0x17847050 2" }, + { "R 0x17847060 2" }, + { "R 0x17847070 2" }, + { "R 0x17847080 2" }, + { "R 0x17847090 2" }, + { "R 0x178470a0 2" }, + { "R 0x178470b0 2" }, + { "R 0x178470c0 2" }, + { "R 0x17850000 2" }, + { "R 0x17850010 2" }, + { "R 0x17850030 2" }, + { "R 0x17850040" }, + { "R 0x17854000" }, + { "R 0x17854008 4" }, + { "R 0x179c8814 2" }, + { "R 0x179d0104" }, + { "R 0x179d0118 2" }, + { "R 0x179d0148 2" }, + { "R 0x179d1600" }, + { "R 0x179d1678" }, + { "R 0x179d1688 2" }, + { "R 0x179d1694 3" }, + { "R 0x179d1820 3" }, + { "R 0x17b70000" }, + { "R 0x17b70008 2" }, + { "R 0x17b71000" }, + { "R 0x17b71008 2" }, + { "R 0x164807f8" }, + { "R 0x16480810 3" }, + { "R 0x16483000 40" }, + { "R 0x16483a00 2" }, + { "R 0x16488908" }, + { "R 0x16488c18" }, + { "R 0x164a8908" }, + { "R 0x164a8c18" }, + { "R 0x164a07f8" }, + { "R 0x164a0810 3" }, + { "R 0x164a3000 40" }, + { "R 0x164a3a00 2" }, + { "R 0x16493000 40" }, + { "R 0x16493a00 2" }, + { "R 0x16498c18" }, + { "R 0x164b8c18" }, + { "R 0x164b3a00 2" }, + { "R 0x16440000 2" }, + { "R 0x16440020 3" }, + { "R 0x16440030" }, + { "R 0x1644003c" }, + { "R 0x16440044 3" }, + { "R 0x16440438" }, + { "R 0x16440500 5" }, + { "R 0x16562000 2" }, + { "R 0x16565004" }, + { "R 0x17000bd0" }, + { "R 0x170404a0" }, + { "R 0x170a0590" }, + { "R 0x170c0330" }, + { "R 0x170c0338" }, + { "R 0x170c0340" }, + { "R 0x170c0518" }, + { "R 0x170c0528" }, + { "R 0x170c0538" }, + { "R 0x170c0560 4" }, + { "R 0x17200bd0" }, + { "R 0x172404a0" }, + { "R 0x172a0590" }, + { "R 0x172c0330" }, + { "R 0x172c0338" }, + { "R 0x172c0340" }, + { "R 0x172c0518" }, + { "R 0x172c0528" }, + { "R 0x172c0538" }, + { "R 0x172c0560 4" }, + { "R 0x1641000c" }, + { "R 0x1641400c" }, + { "R 0x18830320 2" }, + { "R 0x19830320 2" }, + { "R 0x18040010 6" }, + { "R 0x18040040 10" }, + { "R 0x18040090 6" }, + { "R 0x18850020 2" }, + { "R 0x18850060 2" }, + { "R 0x188500a0 2" }, + { "R 0x188500e0 2" }, + { "R 0x18850120 2" }, + { "R 0x18850160 2" }, + { "R 0x189c1000" }, + { "R 0x199c1000" }, + { "R 0x18a30000 9" }, + { "R 0x18a30030" }, + { "R 0x18a3003c 2" }, + { "R 0x19a30000 9" }, + { "R 0x19a30030" }, + { "R 0x19a3003c 2" }, + { "R 0x24201040" }, + { "R 0x24201048" }, + { "R 0x24100010" }, + { "R 0x24100020 6" }, + { "R 0x24180010" }, + { "R 0x24180020 6" }, + { "R 0x24200010" }, + { "R 0x24200020 6" }, + { "R 0x24200410" }, + { "R 0x24200420 6" }, + { "R 0x24102010" }, + { "R 0x24102038" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102008 2" }, + { "R 0x24181010" }, + { "R 0x24181038" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181008 2" }, + { "R 0x24203010" }, + { "R 0x24203038" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203008 2" }, + { "R 0x24203410" }, + { "R 0x24203438" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203408 2" }, + { "R 0x24104018" }, + { "R 0x24104008" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104098" }, + { "R 0x24104088" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24182018" }, + { "R 0x24182008" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182098" }, + { "R 0x24182088" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24204018" }, + { "R 0x24204008" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204098" }, + { "R 0x24204088" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x16801000 2" }, + { "R 0x240ba050" }, + { "R 0x240ba164" }, + { "R 0x240ba280" }, + { "R 0x240ba288 8" }, + { "R 0x240ba2c0 2" }, + { "R 0x24bc0610 11" }, + { "R 0x24bc0640 2" }, + { "R 0x24bc06a0" }, + { "R 0x24fc0610 11" }, + { "R 0x24fc0640 2" }, + { "R 0x24fc06a0" }, + { "R 0x25bc0610 11" }, + { "R 0x25bc0640 2" }, + { "R 0x25bc06a0" }, + { "R 0x25fc0610 11" }, + { "R 0x25fc0640 2" }, + { "R 0x25fc06a0" }, + { "R 0x240a801c 2" }, + { "R 0x240a8038 3" }, + { "R 0x240a8058 5" }, + { "R 0x240a8074 4" }, + { "R 0x240a80a8" }, + { "R 0x240a80b8" }, + { "R 0x240a80ec 5" }, + { "R 0x240a8140" }, + { "R 0x240a8164 2" }, + { "R 0x240a81c4 2" }, + { "R 0x240a81dc 2" }, + { "R 0x240a844c" }, + { "R 0x240a845c" }, + { "R 0x240a84c8 27" }, + { "R 0x240a9000 2" }, + { "R 0x240a9010 2" }, + { "R 0x240a9020 3" }, + { "R 0x240a9034 2" }, + { "R 0x240a9130 3" }, + { "R 0x240a9140 18" }, + { "R 0x240a91ac 6" }, + { "R 0x240a91c8" }, + { "R 0x240a920c" }, + { "R 0x240a9220 2" }, + { "R 0x240a9264" }, + { "R 0x240a9294 7" }, + { "R 0x240a92b8" }, + { "R 0x240a92f8" }, + { "R 0x24800004" }, + { "R 0x24801004" }, + { "R 0x24802004" }, + { "R 0x24803004" }, + { "R 0x24804004" }, + { "R 0x24805004" }, + { "R 0x24806004" }, + { "R 0x24807004" }, + { "R 0x24808004" }, + { "R 0x24809004" }, + { "R 0x2480a004" }, + { "R 0x2480b004" }, + { "R 0x2480c004" }, + { "R 0x2480d004" }, + { "R 0x2480e004" }, + { "R 0x2480f004" }, + { "R 0x24810004" }, + { "R 0x24811004" }, + { "R 0x24812004" }, + { "R 0x24813004" }, + { "R 0x24814004" }, + { "R 0x24815004" }, + { "R 0x24816004" }, + { "R 0x24817004" }, + { "R 0x24818004" }, + { "R 0x24819004" }, + { "R 0x2481a004" }, + { "R 0x2481b004" }, + { "R 0x2481c004" }, + { "R 0x2481d004" }, + { "R 0x2481e004" }, + { "R 0x2481f004" }, + { "R 0x24820004" }, + { "R 0x24821004" }, + { "R 0x24822004" }, + { "R 0x24823004" }, + { "R 0x24843350 2" }, + { "R 0x248433f4 11" }, + { "R 0x248434c0 6" }, + { "R 0x24843600" }, + { "R 0x2484360c" }, + { "R 0x24845040" }, + { "R 0x24845048" }, + { "R 0x24845050" }, + { "R 0x24845058" }, + { "R 0x24845060" }, + { "R 0x24845068" }, + { "R 0x24845070 4" }, + { "R 0x24845090 14" }, + { "R 0x248450cc 2" }, + { "R 0x24845240" }, + { "R 0x248452a0" }, + { "R 0x24845300" }, + { "R 0x24845310" }, + { "R 0x24845320" }, + { "R 0x24845330 3" }, + { "R 0x24847404" }, + { "R 0x2484740c 3" }, + { "R 0x24847448" }, + { "R 0x24847450" }, + { "R 0x24847458 2" }, + { "R 0x24847600" }, + { "R 0x24849000" }, + { "R 0x24849010" }, + { "R 0x2487c000" }, + { "R 0x2487c01c 3" }, + { "R 0x2487c030 8" }, + { "R 0x2487c054 2" }, + { "R 0x2487c078" }, + { "R 0x2487c108 9" }, + { "R 0x2487c20c 3" }, + { "R 0x248a600c 4" }, + { "R 0x248a6020 3" }, + { "R 0x248a6034 2" }, + { "R 0x248a6040" }, + { "R 0x248a6050" }, + { "R 0x248a6058" }, + { "R 0x248a6060 4" }, + { "R 0x248a7020" }, + { "R 0x248a7030 2" }, + { "R 0x248a7078 4" }, + { "R 0x248a708c 6" }, + { "R 0x248e002c" }, + { "R 0x248e009c 2" }, + { "R 0x248e00a8 3" }, + { "R 0x248e00b8" }, + { "R 0x248e00c0 7" }, + { "R 0x248e00e0" }, + { "R 0x248e00e8" }, + { "R 0x248e00f0" }, + { "R 0x248e00f8" }, + { "R 0x248e0100" }, + { "R 0x248e0108" }, + { "R 0x248e0110" }, + { "R 0x248e0118" }, + { "R 0x248e0120" }, + { "R 0x248e0128" }, + { "R 0x248e0150 4" }, + { "R 0x248e0164" }, + { "R 0x248e01e8" }, + { "R 0x248e1010" }, + { "R 0x248e1060 3" }, + { "R 0x248e1070" }, + { "R 0x248e1084 3" }, + { "R 0x248e3004" }, + { "R 0x248e300c" }, + { "R 0x248e4004" }, + { "R 0x248e4010 2" }, + { "R 0x248e4024 2" }, + { "R 0x248e4038 2" }, + { "R 0x248e600c 5" }, + { "R 0x248e700c 5" }, + { "R 0x248e9004" }, + { "R 0x248e9010 3" }, + { "R 0x248e9020 3" }, + { "R 0x248e9030 3" }, + { "R 0x248e9040 3" }, + { "R 0x248e9050 3" }, + { "R 0x248ea004" }, + { "R 0x248ea010 3" }, + { "R 0x248ea020 3" }, + { "R 0x248ea030 3" }, + { "R 0x248ea040 3" }, + { "R 0x248ea050 3" }, + { "R 0x248f001c" }, + { "R 0x248f0050" }, + { "R 0x248f0058" }, + { "R 0x24c00004" }, + { "R 0x24c01004" }, + { "R 0x24c02004" }, + { "R 0x24c03004" }, + { "R 0x24c04004" }, + { "R 0x24c05004" }, + { "R 0x24c06004" }, + { "R 0x24c07004" }, + { "R 0x24c08004" }, + { "R 0x24c09004" }, + { "R 0x24c0a004" }, + { "R 0x24c0b004" }, + { "R 0x24c0c004" }, + { "R 0x24c0d004" }, + { "R 0x24c0e004" }, + { "R 0x24c0f004" }, + { "R 0x24c10004" }, + { "R 0x24c11004" }, + { "R 0x24c12004" }, + { "R 0x24c13004" }, + { "R 0x24c14004" }, + { "R 0x24c15004" }, + { "R 0x24c16004" }, + { "R 0x24c17004" }, + { "R 0x24c18004" }, + { "R 0x24c19004" }, + { "R 0x24c1a004" }, + { "R 0x24c1b004" }, + { "R 0x24c1c004" }, + { "R 0x24c1d004" }, + { "R 0x24c1e004" }, + { "R 0x24c1f004" }, + { "R 0x24c20004" }, + { "R 0x24c21004" }, + { "R 0x24c22004" }, + { "R 0x24c23004" }, + { "R 0x24c43350 2" }, + { "R 0x24c433f4 11" }, + { "R 0x24c434c0 6" }, + { "R 0x24c43600" }, + { "R 0x24c4360c" }, + { "R 0x24c45040" }, + { "R 0x24c45048" }, + { "R 0x24c45050" }, + { "R 0x24c45058" }, + { "R 0x24c45060" }, + { "R 0x24c45068" }, + { "R 0x24c45070 4" }, + { "R 0x24c45090 14" }, + { "R 0x24c450cc 2" }, + { "R 0x24c45240" }, + { "R 0x24c452a0" }, + { "R 0x24c45300" }, + { "R 0x24c45310" }, + { "R 0x24c45320" }, + { "R 0x24c45330 3" }, + { "R 0x24c47404" }, + { "R 0x24c4740c 3" }, + { "R 0x24c47448" }, + { "R 0x24c47450" }, + { "R 0x24c47458 2" }, + { "R 0x24c47600" }, + { "R 0x24c49000" }, + { "R 0x24c49010" }, + { "R 0x24c7c000" }, + { "R 0x24c7c01c 3" }, + { "R 0x24c7c030 8" }, + { "R 0x24c7c054 2" }, + { "R 0x24c7c078" }, + { "R 0x24c7c108 9" }, + { "R 0x24c7c20c 3" }, + { "R 0x24ca600c 4" }, + { "R 0x24ca6020 3" }, + { "R 0x24ca6034 2" }, + { "R 0x24ca6040" }, + { "R 0x24ca6050" }, + { "R 0x24ca6058" }, + { "R 0x24ca6060 4" }, + { "R 0x24ca7020" }, + { "R 0x24ca7030 2" }, + { "R 0x24ca7078 4" }, + { "R 0x24ca708c 6" }, + { "R 0x24ce002c" }, + { "R 0x24ce009c 2" }, + { "R 0x24ce00a8 3" }, + { "R 0x24ce00b8" }, + { "R 0x24ce00c0 7" }, + { "R 0x24ce00e0" }, + { "R 0x24ce00e8" }, + { "R 0x24ce00f0" }, + { "R 0x24ce00f8" }, + { "R 0x24ce0100" }, + { "R 0x24ce0108" }, + { "R 0x24ce0110" }, + { "R 0x24ce0118" }, + { "R 0x24ce0120" }, + { "R 0x24ce0128" }, + { "R 0x24ce0150 4" }, + { "R 0x24ce0164" }, + { "R 0x24ce01e8" }, + { "R 0x24ce1010" }, + { "R 0x24ce1060 3" }, + { "R 0x24ce1070" }, + { "R 0x24ce1084 3" }, + { "R 0x24ce3004" }, + { "R 0x24ce300c" }, + { "R 0x24ce4004" }, + { "R 0x24ce4010 2" }, + { "R 0x24ce4024 2" }, + { "R 0x24ce4038 2" }, + { "R 0x24ce600c 5" }, + { "R 0x24ce700c 5" }, + { "R 0x24ce9004" }, + { "R 0x24ce9010 3" }, + { "R 0x24ce9020 3" }, + { "R 0x24ce9030 3" }, + { "R 0x24ce9040 3" }, + { "R 0x24ce9050 3" }, + { "R 0x24cea004" }, + { "R 0x24cea010 3" }, + { "R 0x24cea020 3" }, + { "R 0x24cea030 3" }, + { "R 0x24cea040 3" }, + { "R 0x24cea050 3" }, + { "R 0x24cf001c" }, + { "R 0x24cf0050" }, + { "R 0x24cf0058" }, + { "R 0x25800004" }, + { "R 0x25801004" }, + { "R 0x25802004" }, + { "R 0x25803004" }, + { "R 0x25804004" }, + { "R 0x25805004" }, + { "R 0x25806004" }, + { "R 0x25807004" }, + { "R 0x25808004" }, + { "R 0x25809004" }, + { "R 0x2580a004" }, + { "R 0x2580b004" }, + { "R 0x2580c004" }, + { "R 0x2580d004" }, + { "R 0x2580e004" }, + { "R 0x2580f004" }, + { "R 0x25810004" }, + { "R 0x25811004" }, + { "R 0x25812004" }, + { "R 0x25813004" }, + { "R 0x25814004" }, + { "R 0x25815004" }, + { "R 0x25816004" }, + { "R 0x25817004" }, + { "R 0x25818004" }, + { "R 0x25819004" }, + { "R 0x2581a004" }, + { "R 0x2581b004" }, + { "R 0x2581c004" }, + { "R 0x2581d004" }, + { "R 0x2581e004" }, + { "R 0x2581f004" }, + { "R 0x25820004" }, + { "R 0x25821004" }, + { "R 0x25822004" }, + { "R 0x25823004" }, + { "R 0x25843350 2" }, + { "R 0x258433f4 11" }, + { "R 0x258434c0 6" }, + { "R 0x25843600" }, + { "R 0x2584360c" }, + { "R 0x25845040" }, + { "R 0x25845048" }, + { "R 0x25845050" }, + { "R 0x25845058" }, + { "R 0x25845060" }, + { "R 0x25845068" }, + { "R 0x25845070 4" }, + { "R 0x25845090 14" }, + { "R 0x258450cc 2" }, + { "R 0x25845240" }, + { "R 0x258452a0" }, + { "R 0x25845300" }, + { "R 0x25845310" }, + { "R 0x25845320" }, + { "R 0x25845330 3" }, + { "R 0x25847404" }, + { "R 0x2584740c 3" }, + { "R 0x25847448" }, + { "R 0x25847450" }, + { "R 0x25847458 2" }, + { "R 0x25847600" }, + { "R 0x25849000" }, + { "R 0x25849010" }, + { "R 0x2587c000" }, + { "R 0x2587c01c 3" }, + { "R 0x2587c030 8" }, + { "R 0x2587c054 2" }, + { "R 0x2587c078" }, + { "R 0x2587c108 9" }, + { "R 0x2587c20c 3" }, + { "R 0x258a600c 4" }, + { "R 0x258a6020 3" }, + { "R 0x258a6034 2" }, + { "R 0x258a6040" }, + { "R 0x258a6050" }, + { "R 0x258a6058" }, + { "R 0x258a6060 4" }, + { "R 0x258a7020" }, + { "R 0x258a7030 2" }, + { "R 0x258a7078 4" }, + { "R 0x258a708c 6" }, + { "R 0x258e002c" }, + { "R 0x258e009c 2" }, + { "R 0x258e00a8 3" }, + { "R 0x258e00b8" }, + { "R 0x258e00c0 7" }, + { "R 0x258e00e0" }, + { "R 0x258e00e8" }, + { "R 0x258e00f0" }, + { "R 0x258e00f8" }, + { "R 0x258e0100" }, + { "R 0x258e0108" }, + { "R 0x258e0110" }, + { "R 0x258e0118" }, + { "R 0x258e0120" }, + { "R 0x258e0128" }, + { "R 0x258e0150 4" }, + { "R 0x258e0164" }, + { "R 0x258e01e8" }, + { "R 0x258e1010" }, + { "R 0x258e1060 3" }, + { "R 0x258e1070" }, + { "R 0x258e1084 3" }, + { "R 0x258e3004" }, + { "R 0x258e300c" }, + { "R 0x258e4004" }, + { "R 0x258e4010 2" }, + { "R 0x258e4024 2" }, + { "R 0x258e4038 2" }, + { "R 0x258e600c 5" }, + { "R 0x258e700c 5" }, + { "R 0x258e9004" }, + { "R 0x258e9010 3" }, + { "R 0x258e9020 3" }, + { "R 0x258e9030 3" }, + { "R 0x258e9040 3" }, + { "R 0x258e9050 3" }, + { "R 0x258ea004" }, + { "R 0x258ea010 3" }, + { "R 0x258ea020 3" }, + { "R 0x258ea030 3" }, + { "R 0x258ea040 3" }, + { "R 0x258ea050 3" }, + { "R 0x258f001c" }, + { "R 0x258f0050" }, + { "R 0x258f0058" }, + { "R 0x25c00004" }, + { "R 0x25c01004" }, + { "R 0x25c02004" }, + { "R 0x25c03004" }, + { "R 0x25c04004" }, + { "R 0x25c05004" }, + { "R 0x25c06004" }, + { "R 0x25c07004" }, + { "R 0x25c08004" }, + { "R 0x25c09004" }, + { "R 0x25c0a004" }, + { "R 0x25c0b004" }, + { "R 0x25c0c004" }, + { "R 0x25c0d004" }, + { "R 0x25c0e004" }, + { "R 0x25c0f004" }, + { "R 0x25c10004" }, + { "R 0x25c11004" }, + { "R 0x25c12004" }, + { "R 0x25c13004" }, + { "R 0x25c14004" }, + { "R 0x25c15004" }, + { "R 0x25c16004" }, + { "R 0x25c17004" }, + { "R 0x25c18004" }, + { "R 0x25c19004" }, + { "R 0x25c1a004" }, + { "R 0x25c1b004" }, + { "R 0x25c1c004" }, + { "R 0x25c1d004" }, + { "R 0x25c1e004" }, + { "R 0x25c1f004" }, + { "R 0x25c20004" }, + { "R 0x25c21004" }, + { "R 0x25c22004" }, + { "R 0x25c23004" }, + { "R 0x25c43350 2" }, + { "R 0x25c433f4 11" }, + { "R 0x25c434c0 6" }, + { "R 0x25c43600" }, + { "R 0x25c4360c" }, + { "R 0x25c45040" }, + { "R 0x25c45048" }, + { "R 0x25c45050" }, + { "R 0x25c45058" }, + { "R 0x25c45060" }, + { "R 0x25c45068" }, + { "R 0x25c45070 4" }, + { "R 0x25c45090 14" }, + { "R 0x25c450cc 2" }, + { "R 0x25c45240" }, + { "R 0x25c452a0" }, + { "R 0x25c45300" }, + { "R 0x25c45310" }, + { "R 0x25c45320" }, + { "R 0x25c45330 3" }, + { "R 0x25c47404" }, + { "R 0x25c4740c 3" }, + { "R 0x25c47448" }, + { "R 0x25c47450" }, + { "R 0x25c47458 2" }, + { "R 0x25c47600" }, + { "R 0x25c49000" }, + { "R 0x25c49010" }, + { "R 0x25c7c000" }, + { "R 0x25c7c01c 3" }, + { "R 0x25c7c030 8" }, + { "R 0x25c7c054 2" }, + { "R 0x25c7c078" }, + { "R 0x25c7c108 9" }, + { "R 0x25c7c20c 3" }, + { "R 0x25ca600c 4" }, + { "R 0x25ca6020 3" }, + { "R 0x25ca6034 2" }, + { "R 0x25ca6040" }, + { "R 0x25ca6050" }, + { "R 0x25ca6058" }, + { "R 0x25ca6060 4" }, + { "R 0x25ca7020" }, + { "R 0x25ca7030 2" }, + { "R 0x25ca7078 4" }, + { "R 0x25ca708c 6" }, + { "R 0x25ce002c" }, + { "R 0x25ce009c 2" }, + { "R 0x25ce00a8 3" }, + { "R 0x25ce00b8" }, + { "R 0x25ce00c0 7" }, + { "R 0x25ce00e0" }, + { "R 0x25ce00e8" }, + { "R 0x25ce00f0" }, + { "R 0x25ce00f8" }, + { "R 0x25ce0100" }, + { "R 0x25ce0108" }, + { "R 0x25ce0110" }, + { "R 0x25ce0118" }, + { "R 0x25ce0120" }, + { "R 0x25ce0128" }, + { "R 0x25ce0150 4" }, + { "R 0x25ce0164" }, + { "R 0x25ce01e8" }, + { "R 0x25ce1010" }, + { "R 0x25ce1060 3" }, + { "R 0x25ce1070" }, + { "R 0x25ce1084 3" }, + { "R 0x25ce3004" }, + { "R 0x25ce300c" }, + { "R 0x25ce4004" }, + { "R 0x25ce4010 2" }, + { "R 0x25ce4024 2" }, + { "R 0x25ce4038 2" }, + { "R 0x25ce600c 5" }, + { "R 0x25ce700c 5" }, + { "R 0x25ce9004" }, + { "R 0x25ce9010 3" }, + { "R 0x25ce9020 3" }, + { "R 0x25ce9030 3" }, + { "R 0x25ce9040 3" }, + { "R 0x25ce9050 3" }, + { "R 0x25cea004" }, + { "R 0x25cea010 3" }, + { "R 0x25cea020 3" }, + { "R 0x25cea030 3" }, + { "R 0x25cea040 3" }, + { "R 0x25cea050 3" }, + { "R 0x25cf001c" }, + { "R 0x25cf0050" }, + { "R 0x25cf0058" }, + { "R 0x240a0008 2" }, + { "R 0x240a1008 2" }, + { "R 0x248e0070 7" }, + { "R 0x248e0094 2" }, + { "R 0x248e012c 9" }, + { "R 0x248e0160" }, + { "R 0x248e0364 2" }, + { "R 0x24ce0070 7" }, + { "R 0x24ce0094 2" }, + { "R 0x24ce012c 9" }, + { "R 0x24ce0160" }, + { "R 0x24ce0364 2" }, + { "R 0x258e0070 7" }, + { "R 0x258e0094 2" }, + { "R 0x258e012c 9" }, + { "R 0x258e0160" }, + { "R 0x258e0364 2" }, + { "R 0x25ce0070 7" }, + { "R 0x25ce0094 2" }, + { "R 0x25ce012c 9" }, + { "R 0x25ce0160" }, + { "R 0x25ce0364 2" }, + { "R 0x248e0358" }, + { "R 0x24ce0358" }, + { "R 0x258e0358" }, + { "R 0x25ce0358" }, + { "R 0x248e0008" }, + { "R 0x24ce0008" }, + { "R 0x258e0008" }, + { "R 0x25ce0008" }, + { "R 0x24076b00 2" }, + { "R 0x24076b0c 2" }, + { "R 0x24076b18 2" }, + { "R 0x24076b24 2" }, + { "R 0x24076b30 2" }, + { "R 0x24076b3c 2" }, + { "R 0x24076b48 2" }, + { "R 0x24076b54 2" }, + { "R 0x24076b60 2" }, + { "R 0x24076b6c 2" }, + { "R 0x24076b78 2" }, + { "R 0x24076b84 2" }, + { "R 0x24076b90 2" }, + { "R 0x24076b9c 2" }, + { "R 0x24076ba8 2" }, + { "R 0x24076bb4 2" }, + { "R 0x24076bc0 2" }, + { "R 0x24076bcc 2" }, + { "R 0x24076bd8 2" }, + { "R 0x24076be4 2" }, + { "R 0x24076bf0 2" }, + { "R 0x24076bfc 2" }, + { "R 0x24076c08 2" }, + { "R 0x24076c14 2" }, + { "R 0x24076c20 2" }, + { "R 0x24076c2c 2" }, + { "R 0x24076c38 2" }, + { "R 0x24076c44 2" }, + { "R 0x24076c50 2" }, + { "R 0x24076c5c 2" }, + { "R 0x24076c68 2" }, + { "R 0x24076c74 2" }, + { "R 0x24076950" }, + { "R 0x240760a4" }, + { "R 0x248720b0" }, + { "R 0x258720b0" }, + { "R 0x24c720b0" }, + { "R 0x25c720b0" }, +}; + +static const struct dcc_register_entry pakala_dcc_entries_ll4[] = { + { "R 0x16801000 2" }, + { "R 0x240e0010" }, + { "R 0x240e0020 8" }, + { "R 0x240e0248" }, + { "R 0x24330010" }, + { "R 0x24330020 8" }, + { "R 0x24330248" }, + { "R 0x240e1018" }, + { "R 0x240e1008" }, + { "R 0x240e1010 2" }, + { "R 0x24331018" }, + { "R 0x24331008" }, + { "R 0x24331010 2" }, + { "R 0x1780010" }, + { "R 0x1780020 8" }, + { "R 0x1780248" }, + { "R 0x1782018" }, + { "R 0x1782008" }, + { "R 0x1782010 2" }, + { "R 0x1783018" }, + { "R 0x1783008" }, + { "R 0x1783010 2" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1681048" }, + { "R 0x1682018" }, + { "R 0x1682008" }, + { "R 0x1682010 2" }, + { "R 0x16e0010" }, + { "R 0x16e0020 8" }, + { "R 0x16e0248" }, + { "R 0x16e1018" }, + { "R 0x16e1008" }, + { "R 0x16e1010 2" }, + { "R 0x16e1098" }, + { "R 0x16e1088" }, + { "R 0x16e1090 2" }, + { "R 0x16e1118" }, + { "R 0x16e1108" }, + { "R 0x16e1110 2" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x1700248" }, + { "R 0x1702018" }, + { "R 0x1702008" }, + { "R 0x1702010 2" }, + { "R 0x1702218" }, + { "R 0x1702208" }, + { "R 0x1702210 2" }, + { "R 0x1702118" }, + { "R 0x1702108" }, + { "R 0x1702110 2" }, + { "R 0x1600010" }, + { "R 0x1600020 8" }, + { "R 0x1600248 2" }, + { "R 0x1600258" }, + { "R 0x1602018" }, + { "R 0x1602008" }, + { "R 0x1602010 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1602118" }, + { "R 0x1602108" }, + { "R 0x1602110 2" }, + { "R 0x1602198" }, + { "R 0x1602188" }, + { "R 0x1602190 2" }, + { "R 0x1602218" }, + { "R 0x1602208" }, + { "R 0x1602210 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1500010" }, + { "R 0x1500020 8" }, + { "R 0x1500248" }, + { "R 0x1500448" }, + { "R 0x1502018" }, + { "R 0x1502008" }, + { "R 0x1502010 2" }, + { "R 0x1502098" }, + { "R 0x1502088" }, + { "R 0x1502090 2" }, + { "R 0x16e00010" }, + { "R 0x16e00020 8" }, + { "R 0x16e00248" }, + { "R 0x16e01018" }, + { "R 0x16e01008" }, + { "R 0x16e01010 2" }, + { "R 0x1b600010" }, + { "R 0x1b600020 8" }, + { "R 0x1b600248" }, + { "R 0x1b601018" }, + { "R 0x1b601008" }, + { "R 0x1b601010 2" }, + { "R 0x16000104 30" }, + { "R 0x16000204 29" }, + { "R 0x16000384 30" }, + { "R 0xb291024" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0xbde1034 2" }, + { "R 0xb201020 2" }, + { "R 0xb211020 2" }, + { "R 0xb221020 2" }, + { "R 0xb231020 2" }, + { "R 0xb204520" }, + { "R 0xb200000" }, + { "R 0xb210000" }, + { "R 0xb220000" }, + { "R 0xb230000" }, + { "R 0x16500010" }, + { "R 0x16510010" }, + { "R 0x16520010" }, + { "R 0x16530010" }, + { "R 0x16500030" }, + { "R 0x16510030" }, + { "R 0x16520030" }, + { "R 0x16530030" }, + { "R 0x16500038" }, + { "R 0x16510038" }, + { "R 0x16520038" }, + { "R 0x16530038" }, + { "R 0x16500040" }, + { "R 0x16510040" }, + { "R 0x16520040" }, + { "R 0x16530040" }, + { "R 0x16500048" }, + { "R 0x16500400 3" }, + { "R 0x16510400 3" }, + { "R 0x16520400 3" }, + { "R 0x16530400 3" }, + { "R 0x16510d3c" }, + { "R 0x16510d54" }, + { "R 0x16510d6c" }, + { "R 0x16510d84" }, + { "R 0x16510d9c" }, + { "R 0x16510db4" }, + { "R 0x16510dcc" }, + { "R 0x16510de4" }, + { "R 0x16510dfc" }, + { "R 0x16510e14" }, + { "R 0x16510e2c" }, + { "R 0x16510e44" }, + { "R 0x16510e5c" }, + { "R 0x16510e74" }, + { "R 0x16510e8c" }, + { "R 0x16510ea4" }, + { "R 0x16510fdc" }, + { "R 0x16510ff4" }, + { "R 0x1651100c" }, + { "R 0x16511024" }, + { "R 0x1651103c" }, + { "R 0x16511054" }, + { "R 0x1651106c" }, + { "R 0x16511084" }, + { "R 0x1651109c" }, + { "R 0x165110b4" }, + { "R 0x165110cc" }, + { "R 0x165110e4" }, + { "R 0x165110fc" }, + { "R 0x16511114" }, + { "R 0x1651112c" }, + { "R 0x16511144" }, + { "R 0x1651127c" }, + { "R 0x16511294" }, + { "R 0x165112ac" }, + { "R 0x165112c4" }, + { "R 0x165112dc" }, + { "R 0x165112f4" }, + { "R 0x1651130c" }, + { "R 0x16511324" }, + { "R 0x1651133c" }, + { "R 0x16511354" }, + { "R 0x1651136c" }, + { "R 0x16511384" }, + { "R 0x1651139c" }, + { "R 0x165113b4" }, + { "R 0x165113cc" }, + { "R 0x165113e4" }, + { "R 0x1651151c" }, + { "R 0x16511534" }, + { "R 0x1651154c" }, + { "R 0x16511564" }, + { "R 0x1651157c" }, + { "R 0x16511594" }, + { "R 0x165115ac" }, + { "R 0x165115c4" }, + { "R 0x165115dc" }, + { "R 0x165115f4" }, + { "R 0x1651160c" }, + { "R 0x16511624" }, + { "R 0x1651163c" }, + { "R 0x16511654" }, + { "R 0x1651166c" }, + { "R 0x16511684" }, + { "R 0x110004 2" }, + { "R 0x11003c 3" }, + { "R 0x176040" }, + { "R 0x10c0000 4" }, + { "R 0x10c1000 2" }, + { "R 0x10c1010 7" }, + { "R 0x10c1100 3" }, + { "R 0x10c1110 5" }, + { "R 0x10c1130 2" }, + { "R 0x10c113c 2" }, + { "R 0x10c1148 3" }, + { "R 0x10c1800 11" }, + { "R 0x10c2000" }, + { "R 0x10cf004" }, + { "R 0x16801000 2" }, +}; + +static const struct dcc_link_config pakala_link_configs[] = { + { + .link_list = 6, + .entries = pakala_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = pakala_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll4), + }, +}; + +static const struct dcc_config pakala_config = { + .lists = pakala_link_configs, + .num_lists = ARRAY_SIZE(pakala_link_configs), +}; + +static const struct dcc_pdata pakala_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10084000, + .ram_size = 0x4000, + .dcc_offset = 0x4000, + .map_ver = 0x3, + .config = &pakala_config, +}; + +#endif /* _QCOM_DCC_PAKALA_CONFIG_H */ From c3f7aa01c1a75c9f4466a4110f05421cae0870d7 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 8 Jan 2026 15:21:50 +0100 Subject: [PATCH 0026/1058] soc: qcom: smem: Expose DDR data from SMEM Most modern Qualcomm platforms (>= SM8150) expose information about the DDR memory present on the system via SMEM. Details from this information is used in various scenarios, such as multimedia drivers configuring the hardware based on the "Highest Bank address Bit" (hbb), or the list of valid frequencies in validation scenarios... Add support for parsing v3-v7 version of the structs. Unforunately, they are not versioned, so some elbow grease is necessary to determine which one is present. See for reference: ver 3: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/1d11897d2cfcc7b85f28ff74c445018dbbecac7a ver 4: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f6e9aa549260bbc0bdcb156c2b05f48dc5963203 ver 5: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/617d3297abe8b1b8dd3de3d1dd69c3961e6f343f ver 5 with 6regions: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/d770e009f9bae58d56d926f7490bbfb45af8341f ver 6: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/62659b557fdb1551b20fae8073d1d701dfa8a62e ver 7: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/734d95599c5ebb1ca0d4e1639142e65c590532b7 Reviewed-by: Bjorn Andersson Signed-off-by: Konrad Dybcio Tested-by: Neil Armstrong # on SM8650-HDK Link: https://lore.kernel.org/r/20260108-topic-smem_dramc-v3-1-6b64df58a017@oss.qualcomm.com --- drivers/soc/qcom/Makefile | 3 +- drivers/soc/qcom/smem.c | 14 +- drivers/soc/qcom/smem.h | 9 + drivers/soc/qcom/smem_dramc.c | 408 ++++++++++++++++++++++++++++++++++ include/linux/soc/qcom/smem.h | 4 + 5 files changed, 436 insertions(+), 2 deletions(-) create mode 100644 drivers/soc/qcom/smem.h create mode 100644 drivers/soc/qcom/smem_dramc.c diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index b7f1d2a573674..798643be3590c 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -23,7 +23,8 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o -obj-$(CONFIG_QCOM_SMEM) += smem.o +qcom_smem-y += smem.o smem_dramc.o +obj-$(CONFIG_QCOM_SMEM) += qcom_smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o CFLAGS_smp2p.o := -I$(src) obj-$(CONFIG_QCOM_SMP2P) += smp2p.o diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index d5c94b47f431f..7e05e0555dcb4 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -4,6 +4,7 @@ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -16,6 +17,8 @@ #include #include +#include "smem.h" + /* * The Qualcomm shared memory system is a allocate only heap structure that * consists of one of more memory areas that can be accessed by the processors @@ -284,6 +287,8 @@ struct qcom_smem { struct smem_partition global_partition; struct smem_partition partitions[SMEM_HOST_COUNT]; + struct dentry *debugfs_dir; + unsigned num_regions; struct smem_region regions[] __counted_by(num_regions); }; @@ -1236,17 +1241,24 @@ static int qcom_smem_probe(struct platform_device *pdev) __smem = smem; + smem->debugfs_dir = smem_dram_parse(smem->dev); + smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(smem->socinfo)) + if (IS_ERR(smem->socinfo)) { + debugfs_remove_recursive(smem->debugfs_dir); + dev_dbg(&pdev->dev, "failed to register socinfo device\n"); + } return 0; } static void qcom_smem_remove(struct platform_device *pdev) { + debugfs_remove_recursive(__smem->debugfs_dir); + platform_device_unregister(__smem->socinfo); /* Set to -EPROBE_DEFER to signal unprobed state */ diff --git a/drivers/soc/qcom/smem.h b/drivers/soc/qcom/smem.h new file mode 100644 index 0000000000000..8bf3f606e1ae8 --- /dev/null +++ b/drivers/soc/qcom/smem.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __QCOM_SMEM_INTERNAL__ +#define __QCOM_SMEM_INTERNAL__ + +#include + +struct dentry *smem_dram_parse(struct device *dev); + +#endif diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c new file mode 100644 index 0000000000000..017bb894a91b6 --- /dev/null +++ b/drivers/soc/qcom/smem_dramc.c @@ -0,0 +1,408 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smem.h" + +#define SMEM_DDR_INFO_ID 603 + +#define MAX_DDR_FREQ_NUM_V3 13 +#define MAX_DDR_FREQ_NUM_V5 14 + +#define MAX_CHAN_NUM 8 +#define MAX_RANK_NUM 2 + +#define DDR_HBB_MIN 13 +#define DDR_HBB_MAX 19 + +#define MAX_SHUB_ENTRIES 8 + +static struct smem_dram *__dram; + +enum ddr_info_version { + INFO_UNKNOWN, + INFO_V3, + INFO_V3_WITH_14_FREQS, + INFO_V4, + INFO_V5, + INFO_V5_WITH_6_REGIONS, + INFO_V6, /* INFO_V6 seems to only have shipped with 6 DDR regions, unlike V7 */ + INFO_V7, + INFO_V7_WITH_6_REGIONS, +}; + +struct smem_dram { + unsigned long frequencies[MAX_DDR_FREQ_NUM_V5]; + u32 num_frequencies; + u8 hbb; +}; + +enum ddr_type { + DDR_TYPE_NODDR = 0, + DDR_TYPE_LPDDR1 = 1, + DDR_TYPE_LPDDR2 = 2, + DDR_TYPE_PCDDR2 = 3, + DDR_TYPE_PCDDR3 = 4, + DDR_TYPE_LPDDR3 = 5, + DDR_TYPE_LPDDR4 = 6, + DDR_TYPE_LPDDR4X = 7, + DDR_TYPE_LPDDR5 = 8, + DDR_TYPE_LPDDR5X = 9, +}; + +/* The data structures below are NOT __packed on purpose! */ + +/* Structs used across multiple versions */ +struct ddr_part_details { + __le16 revision_id1; + __le16 revision_id2; + __le16 width; + __le16 density; +}; + +struct ddr_freq_table { + u32 freq_khz; + u8 enabled; +}; + +/* V3 */ +struct ddr_freq_plan_v3 { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; /* NOTE: some have 14 like v5 */ + u8 num_ddr_freqs; + phys_addr_t clk_period_address; +}; + +struct ddr_details_v3 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3 ddr_freq_tbl; + u8 num_channels; +}; + +/* V4 */ +struct ddr_details_v4 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3 ddr_freq_tbl; + u8 num_channels; + u8 num_ranks[MAX_CHAN_NUM]; + u8 highest_bank_addr_bit[MAX_CHAN_NUM][MAX_RANK_NUM]; +}; + +/* V5 */ +struct shub_freq_table { + u8 enable; + u32 freq_khz; +}; + +struct shub_freq_plan_entry { + u8 num_shub_freqs; + struct shub_freq_table shub_freq[MAX_SHUB_ENTRIES]; +}; + +struct ddr_xbl2quantum_smem_data { + phys_addr_t ssr_cookie_addr; + u32 reserved[10]; +}; + +struct ddr_freq_plan_v5 { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V5]; + u8 num_ddr_freqs; + phys_addr_t clk_period_address; + u32 max_nom_ddr_freq; +}; + +struct ddr_region_v5 { + u64 start_address; + u64 size; + u64 mem_controller_address; + u32 granule_size; /* MiB */ + u8 ddr_rank; +#define DDR_RANK_0 BIT(0) +#define DDR_RANK_1 BIT(1) + u8 segments_start_index; + u64 segments_start_offset; +}; + +struct ddr_regions_v5 { + u32 ddr_region_num; /* We expect this to always be 4 or 6 */ + u64 ddr_rank0_size; + u64 ddr_rank1_size; + u64 ddr_cs0_start_addr; + u64 ddr_cs1_start_addr; + u32 highest_bank_addr_bit; + struct ddr_region_v5 ddr_region[] __counted_by(ddr_region_num); +}; + +struct ddr_details_v5 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v5 ddr_freq_tbl; + u8 num_channels; + u8 _padding; + struct ddr_regions_v5 ddr_regions; +}; + +/* V6 */ +struct ddr_misc_info_v6 { + u32 dsf_version; + u32 reserved[10]; +}; + +/* V7 */ +struct ddr_details_v7 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v5 ddr_freq_tbl; + u8 num_channels; + u8 sct_config; + struct ddr_regions_v5 ddr_regions; +}; + +/** + * qcom_smem_dram_get_hbb(): Get the Highest bank address bit + * + * Context: Check qcom_smem_is_available() before calling this function. + * Because __dram * is initialized by smem_dram_parse(), which is in turn + * called from * qcom_smem_probe(), __dram will only be NULL if the data + * couldn't have been found/interpreted correctly. + * + * Return: 0 on success, -ENODATA on failure. + */ +int qcom_smem_dram_get_hbb(void) +{ + int hbb; + + if (!__dram) + return -ENODATA; + + hbb = __dram->hbb; + if (hbb == 0) + return -ENODATA; + else if (hbb < DDR_HBB_MIN || hbb > DDR_HBB_MAX) + return -EINVAL; + + return hbb; +} +EXPORT_SYMBOL_GPL(qcom_smem_dram_get_hbb); + +static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data, bool additional_freq_entry) +{ + /* This may be 13 or 14 */ + int num_freq_entries = MAX_DDR_FREQ_NUM_V3; + struct ddr_details_v3 *details = data; + + if (additional_freq_entry) + num_freq_entries++; + + for (int i = 0; i < num_freq_entries; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v4 *details = data; + + /* Rank 0 channel 0 entry holds the correct value */ + dram->hbb = details->highest_bank_addr_bit[0][0]; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v5 *details = data; + struct ddr_regions_v5 *region = &details->ddr_regions; + + dram->hbb = region[0].highest_bank_addr_bit; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v7_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v7 *details = data; + struct ddr_regions_v5 *region = &details->ddr_regions; + + dram->hbb = region[0].highest_bank_addr_bit; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +/* The structure contains no version field, so we have to perform some guesswork.. */ +static int smem_dram_infer_struct_version(size_t size) +{ + /* Some early versions provided less bytes of less useful data */ + if (size < sizeof(struct ddr_details_v3)) + return -EINVAL; + + if (size == sizeof(struct ddr_details_v3)) + return INFO_V3; + + if (size == sizeof(struct ddr_details_v3) + + sizeof(struct ddr_freq_table)) + return INFO_V3_WITH_14_FREQS; + + if (size == sizeof(struct ddr_details_v4)) + return INFO_V4; + + if (size == sizeof(struct ddr_details_v5) + + 4 * sizeof(struct ddr_region_v5)) + return INFO_V5; + + if (size == sizeof(struct ddr_details_v5) + + 4 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_xbl2quantum_smem_data) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V5; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5)) + return INFO_V5_WITH_6_REGIONS; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_xbl2quantum_smem_data) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V5_WITH_6_REGIONS; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V6; + + if (size == sizeof(struct ddr_details_v7) + + 4 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V7; + + if (size == sizeof(struct ddr_details_v7) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V7_WITH_6_REGIONS; + + return INFO_UNKNOWN; +} + +static int smem_dram_frequencies_show(struct seq_file *s, void *unused) +{ + struct smem_dram *dram = s->private; + + for (int i = 0; i < dram->num_frequencies; i++) + seq_printf(s, "%lu\n", dram->frequencies[i]); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(smem_dram_frequencies); + +static int smem_hbb_show(struct seq_file *s, void *unused) +{ + struct smem_dram *dram = s->private; + + if (!dram->hbb) + return -EINVAL; + + seq_printf(s, "%d\n", dram->hbb); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(smem_hbb); + +struct dentry *smem_dram_parse(struct device *dev) +{ + struct dentry *debugfs_dir; + enum ddr_info_version ver; + struct smem_dram *dram; + size_t actual_size; + void *data = NULL; + + /* No need to check qcom_smem_is_available(), this func is called by the SMEM driver */ + data = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_DDR_INFO_ID, &actual_size); + if (IS_ERR_OR_NULL(data)) + return ERR_PTR(-ENODATA); + + ver = smem_dram_infer_struct_version(actual_size); + if (ver < 0) { + /* Some SoCs don't provide data that's useful for us */ + return ERR_PTR(-ENODATA); + } else if (ver == INFO_UNKNOWN) { + /* In other cases, we may not have added support for a newer struct revision */ + pr_err("Found an unknown type of DRAM info struct (size = %zu)\n", actual_size); + return ERR_PTR(-EINVAL); + } + + dram = devm_kzalloc(dev, sizeof(*dram), GFP_KERNEL); + if (!dram) + return ERR_PTR(-ENOMEM); + + switch (ver) { + case INFO_V3: + smem_dram_parse_v3_data(dram, data, false); + break; + case INFO_V3_WITH_14_FREQS: + smem_dram_parse_v3_data(dram, data, true); + break; + case INFO_V4: + smem_dram_parse_v4_data(dram, data); + break; + case INFO_V5: + case INFO_V5_WITH_6_REGIONS: + case INFO_V6: + smem_dram_parse_v5_data(dram, data); + break; + case INFO_V7: + case INFO_V7_WITH_6_REGIONS: + smem_dram_parse_v7_data(dram, data); + break; + default: + return ERR_PTR(-EINVAL); + } + + /* Both the entry and its parent dir will be cleaned up by debugfs_remove_recursive */ + debugfs_dir = debugfs_create_dir("qcom_smem", NULL); + debugfs_create_file("dram_frequencies", 0444, debugfs_dir, dram, + &smem_dram_frequencies_fops); + debugfs_create_file("hbb", 0444, debugfs_dir, dram, &smem_hbb_fops); + + /* If there was no failure so far, assign the global variable */ + __dram = dram; + + return debugfs_dir; +} diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h index f946e3beca215..223cd5090a2a8 100644 --- a/include/linux/soc/qcom/smem.h +++ b/include/linux/soc/qcom/smem.h @@ -2,6 +2,8 @@ #ifndef __QCOM_SMEM_H__ #define __QCOM_SMEM_H__ +#include + #define QCOM_SMEM_HOST_ANY -1 bool qcom_smem_is_available(void); @@ -17,4 +19,6 @@ int qcom_smem_get_feature_code(u32 *code); int qcom_smem_bust_hwspin_lock_by_host(unsigned int host); +int qcom_smem_dram_get_hbb(void); + #endif From c35a974bb284caa5d4e957d2680cbdddf024a4d5 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 5 Mar 2026 16:04:23 +0530 Subject: [PATCH 0027/1058] WORKAROUND: soc: qcom: smem_dramc: Fix v3 DDR freq table out-of-bounds Some SMEM v3 DDR details blobs contain 14 frequency entries, while the parser assumes MAX_DDR_FREQ_NUM_V3. This can lead to out-of-bounds reads and hangs during smem_dram_parse(). Handle the 14-entry v3 layout explicitly and parse it with the correct bounds based on the SMEM item size. Signed-off-by: Komal Bajaj --- drivers/soc/qcom/smem_dramc.c | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c index 017bb894a91b6..dc2cd7e13b88e 100644 --- a/drivers/soc/qcom/smem_dramc.c +++ b/drivers/soc/qcom/smem_dramc.c @@ -78,7 +78,7 @@ struct ddr_freq_table { /* V3 */ struct ddr_freq_plan_v3 { - struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; /* NOTE: some have 14 like v5 */ + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; u8 num_ddr_freqs; phys_addr_t clk_period_address; }; @@ -91,6 +91,21 @@ struct ddr_details_v3 { u8 num_channels; }; +/* Some V3 structs have an additional frequency level */ +struct ddr_freq_plan_v3_14freqs { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3 + 1]; + u8 num_ddr_freqs; + phys_addr_t clk_period_address; +}; + +struct ddr_details_v3_14freqs { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3_14freqs ddr_freq_tbl; + u8 num_channels; +}; + /* V4 */ struct ddr_details_v4 { u8 manufacturer_id; @@ -201,16 +216,11 @@ int qcom_smem_dram_get_hbb(void) } EXPORT_SYMBOL_GPL(qcom_smem_dram_get_hbb); -static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data, bool additional_freq_entry) +static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data) { - /* This may be 13 or 14 */ - int num_freq_entries = MAX_DDR_FREQ_NUM_V3; struct ddr_details_v3 *details = data; - if (additional_freq_entry) - num_freq_entries++; - - for (int i = 0; i < num_freq_entries; i++) { + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) { struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; if (freq_entry->freq_khz && freq_entry->enabled) @@ -218,6 +228,18 @@ static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data, bool add } } +static void smem_dram_parse_v3_14freqs_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v3_14freqs *details = data; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3 + 1; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data) { struct ddr_details_v4 *details = data; @@ -273,8 +295,7 @@ static int smem_dram_infer_struct_version(size_t size) if (size == sizeof(struct ddr_details_v3)) return INFO_V3; - if (size == sizeof(struct ddr_details_v3) - + sizeof(struct ddr_freq_table)) + if (size == sizeof(struct ddr_details_v3_14freqs)) return INFO_V3_WITH_14_FREQS; if (size == sizeof(struct ddr_details_v4)) @@ -374,10 +395,10 @@ struct dentry *smem_dram_parse(struct device *dev) switch (ver) { case INFO_V3: - smem_dram_parse_v3_data(dram, data, false); + smem_dram_parse_v3_data(dram, data); break; case INFO_V3_WITH_14_FREQS: - smem_dram_parse_v3_data(dram, data, true); + smem_dram_parse_v3_14freqs_data(dram, data); break; case INFO_V4: smem_dram_parse_v4_data(dram, data); From 0aa90b7d45babe6116bcbb3006ae4636256b6e0f Mon Sep 17 00:00:00 2001 From: Tony Truong Date: Fri, 10 Apr 2026 11:02:30 +0530 Subject: [PATCH 0028/1058] FROMLIST: drivers: soc: qcom: smem: Switch partitions to xarray The partitions array is currently statically sized and uses the remote host ID as an index. Future protocol improvements to allow for more than two hosts in a partition will require hostIDs to be bitwise significant integers. This will result in large, sparse host IDs that generally exceed the current static limit. Switch to using xarray to efficiently handle these sparse indices and allow for dynamic growth. Signed-off-by: Tony Truong Signed-off-by: Pranav Mahesh Phansalkar Tested-by: Konrad Dybcio # Glymur CRD Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260410-smem-v1-1-8e94bb5416a6@oss.qualcomm.com --- drivers/soc/qcom/smem.c | 56 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 7e05e0555dcb4..4315512d3a1d4 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -88,9 +88,6 @@ /* Processor/host identifier for the global partition */ #define SMEM_GLOBAL_HOST 0xfffe -/* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 25 - /** * struct smem_proc_comm - proc_comm communication struct (legacy) * @command: current command to be executed @@ -285,7 +282,7 @@ struct qcom_smem { struct platform_device *socinfo; struct smem_ptable *ptable; struct smem_partition global_partition; - struct smem_partition partitions[SMEM_HOST_COUNT]; + struct xarray partitions; struct dentry *debugfs_dir; @@ -387,7 +384,7 @@ static struct qcom_smem *__smem = INIT_ERR_PTR(-EPROBE_DEFER); int qcom_smem_bust_hwspin_lock_by_host(unsigned int host) { /* This function is for remote procs, so ignore SMEM_HOST_APPS */ - if (host == SMEM_HOST_APPS || host >= SMEM_HOST_COUNT) + if (host == SMEM_HOST_APPS || !xa_load(&__smem->partitions, host)) return -EINVAL; return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host)); @@ -535,8 +532,8 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) if (ret) return ret; - if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { - part = &__smem->partitions[host]; + part = xa_load(&__smem->partitions, host); + if (part) { ret = qcom_smem_alloc_private(__smem, part, item, size); } else if (__smem->global_partition.virt_base) { part = &__smem->global_partition; @@ -702,8 +699,8 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size) if (item >= __smem->item_count) return ERR_PTR(-EINVAL); - if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { - part = &__smem->partitions[host]; + part = xa_load(&__smem->partitions, host); + if (part) { ptr = qcom_smem_get_private(__smem, part, item, size); } else if (__smem->global_partition.virt_base) { part = &__smem->global_partition; @@ -735,8 +732,8 @@ int qcom_smem_get_free_space(unsigned host) if (IS_ERR(__smem)) return PTR_ERR(__smem); - if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { - part = &__smem->partitions[host]; + part = xa_load(&__smem->partitions, host); + if (part) { phdr = part->virt_base; ret = le32_to_cpu(phdr->offset_free_cached) - le32_to_cpu(phdr->offset_free_uncached); @@ -779,12 +776,11 @@ phys_addr_t qcom_smem_virt_to_phys(void *p) { struct smem_partition *part; struct smem_region *area; + unsigned long index; u64 offset; u32 i; - for (i = 0; i < SMEM_HOST_COUNT; i++) { - part = &__smem->partitions[i]; - + xa_for_each(&__smem->partitions, index, part) { if (addr_in_range(part->virt_base, part->size, p)) { offset = p - part->virt_base; @@ -1021,16 +1017,20 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) { struct smem_partition_header *header; + struct smem_partition *part; struct smem_ptable_entry *entry; struct smem_ptable *ptable; u16 remote_host; u16 host0, host1; + int ret; int i; ptable = qcom_smem_get_ptable(smem); if (IS_ERR(ptable)) return PTR_ERR(ptable); + xa_init(&smem->partitions); + for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { entry = &ptable->entry[i]; if (!le32_to_cpu(entry->offset)) @@ -1047,12 +1047,7 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) else continue; - if (remote_host >= SMEM_HOST_COUNT) { - dev_err(smem->dev, "bad host %u\n", remote_host); - return -EINVAL; - } - - if (smem->partitions[remote_host].virt_base) { + if (xa_load(&smem->partitions, remote_host)) { dev_err(smem->dev, "duplicate host %u\n", remote_host); return -EINVAL; } @@ -1061,11 +1056,20 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) if (!header) return -EINVAL; - smem->partitions[remote_host].virt_base = (void __iomem *)header; - smem->partitions[remote_host].phys_base = smem->regions[0].aux_base + - le32_to_cpu(entry->offset); - smem->partitions[remote_host].size = le32_to_cpu(entry->size); - smem->partitions[remote_host].cacheline = le32_to_cpu(entry->cacheline); + part = devm_kzalloc(smem->dev, sizeof(struct smem_partition), GFP_KERNEL); + if (!part) + return -ENOMEM; + + part->virt_base = (void __iomem *)header; + part->phys_base = smem->regions[0].aux_base + le32_to_cpu(entry->offset); + part->size = le32_to_cpu(entry->size); + part->cacheline = le32_to_cpu(entry->cacheline); + + ret = xa_insert(&smem->partitions, remote_host, part, GFP_KERNEL); + if (ret) { + dev_err(smem->dev, "fail to insert host %u\n", remote_host); + return ret; + } } return 0; @@ -1234,7 +1238,6 @@ static int qcom_smem_probe(struct platform_device *pdev) return -EINVAL; } - BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT); ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); if (ret < 0 && ret != -ENOENT) return ret; @@ -1261,6 +1264,7 @@ static void qcom_smem_remove(struct platform_device *pdev) platform_device_unregister(__smem->socinfo); + xa_destroy(&__smem->partitions); /* Set to -EPROBE_DEFER to signal unprobed state */ __smem = ERR_PTR(-EPROBE_DEFER); } From d2b684d4e5b36500580ec454a89441903f6ab329 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 14 May 2026 18:06:38 +0800 Subject: [PATCH 0029/1058] QCLINUX: qcom-dcc: add shikra register list and move config to header Add the DCC register capture list for the Shikra platform (SoC IDs 756, 758, 759) across two linked lists and move the configuration into a dedicated header qcom-dcc-shikra-config.h. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 8 + drivers/misc/qcom-dcc-shikra-config.h | 677 ++++++++++++++++++++++++++ 2 files changed, 685 insertions(+) create mode 100644 drivers/misc/qcom-dcc-shikra-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index a77b5bc144982..73994f39de30e 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -11,6 +11,7 @@ #include "qcom-dcc-lemans-config.h" #include "qcom-dcc-kodiak-config.h" #include "qcom-dcc-pakala-config.h" +#include "qcom-dcc-shikra-config.h" #define DEV_NAME "qcom-dcc" @@ -131,6 +132,13 @@ static int __init dcc_dev_init(void) goto fail; break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(dcc_pdev, &shikra_pdata, sizeof(shikra_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); ret = -EINVAL; diff --git a/drivers/misc/qcom-dcc-shikra-config.h b/drivers/misc/qcom-dcc-shikra-config.h new file mode 100644 index 0000000000000..fdf3d0c34695c --- /dev/null +++ b/drivers/misc/qcom-dcc-shikra-config.h @@ -0,0 +1,677 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_SHIKRA_CONFIG_H +#define _QCOM_DCC_SHIKRA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry shikra_dcc_entries_ll2[] = { + /* timer */ + { "R 0x17421000 2" }, + /* clock */ + { "R 0x1400000 10" }, + { "R 0x1401000 10" }, + { "R 0x1402000 10" }, + { "R 0x1403000 10" }, + { "R 0x1404000 10" }, + { "R 0x1405000 10" }, + { "R 0x1406000 10" }, + { "R 0x1407000 10" }, + { "R 0x1408000 10" }, + { "R 0x1409000 9" }, + { "R 0x140a000 10" }, + { "R 0x140b000 10" }, + { "R 0x140c000 10" }, + { "R 0x141001c" }, + { "R 0x14103d0" }, + { "R 0x1414024" }, + { "R 0x1415034 2" }, + { "R 0x141f02c" }, + { "R 0x141f15c" }, + { "R 0x141f28c" }, + { "R 0x141f3bc" }, + { "R 0x141f4ec" }, + { "R 0x141f61c" }, + { "R 0x141f74c" }, + { "R 0x141f87c" }, + { "R 0x141f9ac" }, + { "R 0x141fadc" }, + { "R 0x141fc0c" }, + { "R 0x1427024" }, + { "R 0x1432034" }, + { "R 0x1434028" }, + { "R 0x1434154" }, + { "R 0x143c018" }, + { "R 0x1446024" }, + { "R 0x1446154" }, + { "R 0x1449018" }, + { "R 0x14b4014" }, + { "R 0x146b000 14" }, + { "R 0xfa80000 6" }, + { "R 0xfa8001c 2" }, + { "R 0xfa80028" }, + { "R 0xfa80034 2" }, + { "R 0xfa80080 3" }, + { "R 0xfa84000 6" }, + { "R 0xfa8401c 2" }, + { "R 0xfa84028" }, + { "R 0xfa84034 2" }, + { "R 0xfa84080 3" }, + { "R 0xfa88000 6" }, + { "R 0xfa8801c 2" }, + { "R 0xfa88028" }, + { "R 0xfa88034 2" }, + { "R 0xfa88080 3" }, + { "R 0x440c000" }, + { "R 0x440c008" }, + { "R 0x440c040 9" }, + { "R 0x440c068 2" }, + /* global_cpr */ + { "R 0x1648000 2" }, + { "R 0x16480e0" }, + { "R 0x1648100" }, + { "R 0x1648120" }, + { "R 0x1648140" }, + { "R 0x1648200" }, + { "R 0x164880c 4" }, + { "R 0x164c000 2" }, + { "R 0x164c0e0" }, + { "R 0x164c100" }, + { "R 0x164c120" }, + { "R 0x164c140" }, + { "R 0x164c200" }, + { "R 0x164c80c 4" }, + { "R 0x1b44268 7" }, + { "R 0x1b44288 11" }, + { "R 0x1b442d0" }, + /* cpr */ + { "R 0xfd9001c 3" }, + { "R 0xfd90090" }, + { "R 0xfd900b0 2" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348 3" }, + { "R 0xfd90360" }, + { "R 0xfd90368 2" }, + { "R 0xfd9101c 3" }, + { "R 0xfd91090" }, + { "R 0xfd910b0 2" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348 3" }, + { "R 0xfd91360" }, + { "R 0xfd91368 2" }, + { "R 0xfd9201c 3" }, + { "R 0xfd92090" }, + { "R 0xfd920b0 2" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348 4" }, + { "R 0xfd92360" }, + { "R 0xfd92368 2" }, + { "R 0xfd98004" }, + { "R 0xfd98018 3" }, + { "R 0xf900c14 2" }, + { "R 0xfba0008" }, + { "R 0xfba0020 2" }, + { "R 0xfba0070" }, + { "R 0xfba0810" }, + { "R 0xfba3500" }, + { "R 0xfba3a84 2" }, + { "R 0xfa90004" }, + { "R 0xfa92004" }, + { "R 0xfa94004" }, + { "R 0xfba3a84 3" }, + { "R 0xfd90200 12" }, + { "R 0xfd91200 12" }, + { "R 0xfd92200 12" }, + { "R 0xfba3500 40" }, + /* cpucp */ + { "R 0xfd80110" }, + { "R 0xfd9001c" }, + { "R 0xfd90090" }, + { "R 0xfd900b0" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348" }, + { "R 0xfd9101c" }, + { "R 0xfd91090" }, + { "R 0xfd910b0" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348" }, + { "R 0xfd9201c" }, + { "R 0xfd92090" }, + { "R 0xfd920b0" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348" }, + { "R 0xfd98004" }, + { "R 0xfd98018" }, + { "R 0xf900c00" }, + { "R 0xfb00000" }, + { "R 0xfba0000" }, + { "R 0xf800000" }, + { "R 0xf810000" }, + { "R 0xf820000" }, + { "R 0xf830000" }, + { "R 0xf840000" }, + { "R 0xf850000" }, + { "R 0xf860000" }, + { "R 0xf870000" }, + { "R 0xfd91000" }, + { "R 0xfd92000" }, + { "R 0xf880000" }, + { "R 0xfd90000" }, + { "R 0xf900c18" }, + { "R 0xfd9134c" }, + { "R 0xfd9234c" }, + { "R 0xfd9034c" }, + { "R 0xfba3a84" }, + { "R 0xfba3a88" }, + { "R 0xfba3a8c" }, + { "R 0xfd91020" }, + { "R 0xfd92020" }, + { "R 0xfd90020" }, + /* modem */ + { "R 0x6080400 3" }, + { "R 0x6080410 2" }, + { "R 0x6080060 5" }, + { "R 0x61f100c" }, + { "R 0x143314c" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0xd2f010" }, + { "R 0x6104000 8" }, + { "R 0x6140208 3" }, + { "R 0x6140228 3" }, + { "R 0x6140248 3" }, + { "R 0x6140268 3" }, + { "R 0x6140288 3" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0x6140200" }, + { "R 0x6140404" }, + { "R 0x608030c" }, + /* ICB - SYSTEM_NOC */ + { "R 0x1880000" }, + { "R 0x1880004" }, + { "R 0x1880008" }, + { "R 0x1880010" }, + { "R 0x1880020" }, + { "R 0x1880024" }, + { "R 0x1880028" }, + { "R 0x188002c" }, + { "R 0x1880030" }, + { "R 0x1880034" }, + { "R 0x1880038" }, + { "R 0x188003c" }, + { "R 0x1880240" }, + { "R 0x1880248" }, + { "R 0x1881018" }, + { "R 0x1881008" }, + { "R 0x1881010 2" }, + { "R 0x1881098" }, + { "R 0x1881088" }, + { "R 0x1881090 2" }, + { "R 0x1881118" }, + { "R 0x1881108" }, + { "R 0x1881110 2" }, + { "R 0x1881198" }, + { "R 0x1881188" }, + { "R 0x1881190 2" }, + { "R 0x1881218" }, + { "R 0x1881208" }, + { "R 0x1881210 2" }, + /* ICB - CONFIG_NOC */ + { "R 0x1900000" }, + { "R 0x1900004" }, + { "R 0x1900008" }, + { "R 0x1900010" }, + { "R 0x1900020" }, + { "R 0x1900024" }, + { "R 0x1900028" }, + { "R 0x190002c" }, + { "R 0x1900030" }, + { "R 0x1900034" }, + { "R 0x1900038" }, + { "R 0x190003c" }, + { "R 0x1900240" }, + { "R 0x1900244" }, + { "R 0x1900248" }, + { "R 0x190024c" }, + { "R 0x1901018" }, + { "R 0x1901008" }, + { "R 0x1901010 2" }, + { "R 0x1901118" }, + { "R 0x1901108" }, + { "R 0x1901110 2" }, + { "R 0x1901218" }, + { "R 0x1901208" }, + { "R 0x1901210 2" }, + { "R 0x1901318" }, + { "R 0x1901308" }, + { "R 0x1901310 2" }, + /* ICB - MEMNOC */ + { "R 0xd00000" }, + { "R 0xd00004" }, + { "R 0xd00008" }, + { "R 0xd00010" }, + { "R 0xd00020" }, + { "R 0xd00024" }, + { "R 0xd00028" }, + { "R 0xd0002c" }, + { "R 0xd00030" }, + { "R 0xd00034" }, + { "R 0xd00038" }, + { "R 0xd0003c" }, + { "R 0xd40000" }, + { "R 0xd40004" }, + { "R 0xd40008" }, + { "R 0xd40010" }, + { "R 0xd40020" }, + { "R 0xd40024" }, + { "R 0xd40028" }, + { "R 0xd4002c" }, + { "R 0xd40030" }, + { "R 0xd40034" }, + { "R 0xd40038" }, + { "R 0xd4003c" }, + { "R 0xd00240" }, + { "R 0xd00248" }, + { "R 0xd40440" }, + { "R 0xd40448" }, + { "R 0xd41018" }, + { "R 0xd41008" }, + { "R 0xd41010 2" }, + { "R 0xd01018" }, + { "R 0xd01008" }, + { "R 0xd01010 2" }, + /* ICB - DC_NOC */ + { "R 0xce5018" }, + { "R 0xce5008" }, + { "R 0xce5010 2" }, + { "R 0xce0010" }, + { "R 0xce0020 8" }, + { "R 0xce0248" }, + /* ICB - QoS - system noc */ + { "R 0x18d1010" }, + { "R 0x18d2010" }, + { "R 0x18d3010" }, + { "R 0x18d4010" }, + { "R 0x18d5010" }, + { "R 0x18d6010" }, + { "R 0x18d7010" }, + { "R 0x18d8010" }, + { "R 0x18d9010" }, + { "R 0x18da010" }, + { "R 0x18db010" }, + { "R 0x18dc010" }, + { "R 0x18dd010" }, + { "R 0x18de010" }, + { "R 0x18df010" }, + { "R 0x18e0010" }, + { "R 0x18e1010" }, + { "R 0x18e2010" }, + { "R 0x18e3010" }, + { "R 0x18e4010" }, + { "R 0x18e5010" }, + { "R 0x18e6010" }, + { "R 0x18e7010" }, + { "R 0x18e8010" }, + { "R 0x18e9010" }, + { "R 0x18ea010" }, + /* ICB - QoS - mem noc */ + { "R 0xd28010" }, + { "R 0xd2a010" }, + { "R 0xd2b010" }, + { "R 0xd2c010" }, + { "R 0xd2d010" }, + { "R 0xd2e010" }, + { "R 0xd2f010" }, + /* ddr */ + { "R 0x1089180 2" }, + { "R 0x10804d4" }, + { "R 0x10804b8 2" }, + { "R 0x1089100" }, + { "R 0x1089110" }, + { "R 0x1089120" }, + { "R 0x10891a0" }, + { "R 0x108340c" }, + { "R 0x1083404" }, + { "R 0x1083410" }, + { "R 0x1083408" }, + { "R 0x1083400" }, + { "R 0x1086418" }, + { "R 0x1086400" }, + { "R 0x1086420" }, + { "R 0x1086410" }, + { "R 0x10891c0" }, + { "R 0x10891e0" }, + { "R 0x1085b14" }, + { "R 0x1085b10" }, + { "R 0x1085b0c" }, + { "R 0x1085b00" }, + { "R 0x10853b0" }, + { "R 0x1085b1c" }, + { "R 0x1085b08" }, + { "R 0x1085b38" }, + { "R 0x1085b30" }, + { "R 0x1085b2c" }, + { "R 0x1085804" }, + { "R 0x1085b28" }, + { "R 0x1085b18" }, + { "R 0x1085230" }, + { "R 0x1085210" }, + { "R 0xc800b0 2" }, + { "R 0xcb6000" }, + { "R 0x1286074 5" }, + { "R 0x1286260 5" }, + { "R 0xc80018" }, + { "R 0xc80108" }, + { "R 0xc840e0 2" }, + { "R 0xcba070 2" }, + { "R 0xcba054" }, + { "R 0xcba078 2" }, + { "R 0xcba058" }, + { "R 0xcba080" }, + { "R 0xcba084" }, + { "R 0xcba05c" }, + { "R 0xcba088" }, + { "R 0xcba08c" }, + { "R 0xcba060" }, + { "R 0xcba090 2" }, + { "R 0xcba064" }, + { "R 0xcba098 2" }, + { "R 0x1090018" }, + { "R 0x1090110 4" }, + { "R 0x1090004" }, + { "R 0x10900a0" }, + { "R 0x1090170" }, + { "R 0x1090180 4" }, + { "R 0x1090078" }, + { "R 0x1090150 4" }, + { "R 0x1090080" }, + { "R 0x1090088" }, + { "R 0x1090090" }, + { "R 0x1090070 2" }, + { "R 0x10900b0" }, + { "R 0x1090130" }, + { "R 0x1090140" }, + { "R 0x1090030 3" }, + { "R 0x1090044" }, + { "R 0x1090144" }, + { "R 0x1090040 3" }, + { "R 0x10900c8 2" }, + { "R 0x1090050" }, + { "R 0x1090128 2" }, + { "R 0x10900e4 5" }, + { "R 0x1090124" }, + { "R 0x1090100" }, + { "R 0xe90018" }, + { "R 0xe90110 4" }, + { "R 0xe90004" }, + { "R 0xe900a0" }, + { "R 0xe90170" }, + { "R 0xe90180 4" }, + { "R 0xe90078" }, + { "R 0xe90150" }, + { "R 0xe90080" }, + { "R 0xe90154" }, + { "R 0xe90088" }, + { "R 0xe90158" }, + { "R 0xe90090" }, + { "R 0xe9015c" }, + { "R 0xe90070 2" }, + { "R 0xe900b0" }, + { "R 0xe90130" }, + { "R 0xe90034" }, + { "R 0xe90140" }, + { "R 0xe90038" }, + { "R 0xe90030" }, + { "R 0xe90044" }, + { "R 0xe90144" }, + { "R 0xe90048" }, + { "R 0xe90040" }, + { "R 0xe900c8 2" }, + { "R 0xe90050" }, + { "R 0xe90128 2" }, + { "R 0xe900e4 3" }, + { "R 0xe900f0 2" }, + { "R 0xe90124" }, + { "R 0xe90100" }, + { "R 0xf90018" }, + { "R 0xf90110 4" }, + { "R 0xf90004" }, + { "R 0xf900a0" }, + { "R 0xf90170" }, + { "R 0xf90180 4" }, + { "R 0xf90078" }, + { "R 0xf90150 4" }, + { "R 0xf90080" }, + { "R 0xf90088" }, + { "R 0xf90090" }, + { "R 0xf90070 2" }, + { "R 0xf900b0" }, + { "R 0xf90130 2" }, + { "R 0xf90140" }, + { "R 0xf90038" }, + { "R 0xf90030" }, + { "R 0xf90044" }, + { "R 0xf90144" }, + { "R 0xf90048" }, + { "R 0xf90040" }, + { "R 0xf900c8 2" }, + { "R 0xf90050" }, + { "R 0xf90128 2" }, + { "R 0xf900e4 5" }, + { "R 0xf90124" }, + { "R 0xf90100" }, + { "R 0xcba218" }, + { "R 0xcba050" }, + { "R 0xcba210" }, + { "R 0xcba280" }, + { "R 0xcba180 4" }, + { "R 0xcba214" }, + { "R 0xcba004" }, + { "R 0xcba000" }, + { "R 0xcba014 2" }, + { "R 0xcba020 2" }, + { "R 0xcba010" }, + { "R 0xcba288 7" }, + { "R 0xcba150 2" }, + { "R 0xcba200" }, + { "R 0xcba140 2" }, + { "R 0xcba230 2" }, + { "R 0xcba0c8 2" }, + { "R 0xcba0b0 4" }, + { "R 0xcba240 2" }, + { "R 0xcba250 4" }, + { "R 0xcba100 5" }, + { "R 0xcba120 3" }, + { "R 0xcba130" }, + { "R 0xcba134" }, + { "R 0xcba270" }, + { "R 0xc35008" }, + { "R 0xc350b4" }, + { "R 0xc35100" }, + { "R 0x1059070" }, + { "R 0x103801c 7" }, + { "R 0x1023318" }, + { "R 0x1020488" }, + { "R 0x1020480" }, + { "R 0x1023594" }, + { "R 0x102358c" }, + { "R 0x10223a0" }, + { "R 0x1022398" }, + { "R 0x10223ac" }, + { "R 0x10223a4" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0x1280100" }, + { "R 0x1281100" }, + { "R 0x1282100" }, + { "R 0x1283100" }, + { "R 0x1284100" }, + { "R 0x1285100" }, + { "R 0x128011c" }, + { "R 0x128111c" }, + { "R 0x128211c" }, + { "R 0x128311c" }, + { "R 0x128411c" }, + { "R 0x128511c" }, + { "R 0x1280568" }, + { "R 0x1281568" }, + { "R 0x1282568" }, + { "R 0x1283568" }, + { "R 0x1284568" }, + { "R 0x1285568" }, + { "R 0x128082c" }, + { "R 0x128182c" }, + { "R 0x128282c" }, + { "R 0x128382c" }, + { "R 0x128482c" }, + { "R 0x128582c" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0xc80058 2" }, + { "R 0xc800c8" }, + { "R 0xc800d4" }, + { "R 0xc80114" }, + { "R 0xc80104 2" }, + { "R 0xc800b0 2" }, + { "R 0xc80098" }, + { "R 0xd00248" }, +}; + +static const struct dcc_register_entry shikra_dcc_entries_ll3[] = { + /* gpu */ + { "R 0x599106c" }, + { "R 0x599100c" }, + { "R 0x59910a4" }, + { "R 0x5991054" }, + { "R 0x5991098 2" }, + { "R 0x5991078" }, + { "R 0x5991508" }, + { "R 0x599150c" }, + { "R 0x143600c" }, + { "R 0x1471000" }, + { "R 0x1436018" }, + /* cdsp */ + { "R 0xb3b0208 3" }, + { "R 0xb3b0228 3" }, + { "R 0xb3b0248 3" }, + { "R 0xb3b0268 3" }, + { "R 0xb3b0290" }, + { "R 0xb3b02b0" }, + { "R 0xb3b0400 3" }, + { "R 0xb302028" }, + { "R 0xb300304" }, + { "R 0xb3b0200" }, + { "R 0xb3b0404" }, + { "R 0x608030c" }, + /* apps_pcu */ + { "R 0xf800024" }, + { "R 0xf800040" }, + { "R 0xf80004c" }, + { "R 0xf800054" }, + { "R 0xf810024" }, + { "R 0xf810040" }, + { "R 0xf81004c" }, + { "R 0xf810054" }, + { "R 0xf820024" }, + { "R 0xf820040" }, + { "R 0xf82004c" }, + { "R 0xf820054" }, + { "R 0xf830024" }, + { "R 0xf830040" }, + { "R 0xf83004c" }, + { "R 0xf830054" }, + { "R 0xf880024" }, + { "R 0xf880040" }, + { "R 0xf880098" }, + { "R 0xfa80000 2" }, + { "R 0xfa84000 2" }, + { "R 0xfa88000 2" }, + { "R 0xf880200" }, + { "R 0xf8801b4 3" }, + { "R 0xf880044 3" }, + { "R 0xf880054" }, + { "R 0xf88006c" }, + { "R 0xf880070 4" }, + { "R 0xfd90348 2" }, + { "R 0xfd91348 2" }, + { "R 0xfd92348 2" }, + { "R 0xfd800fc" }, + { "R 0xfd800ec" }, + { "R 0xfd8010c" }, + { "R 0xfd91060 8" }, + { "R 0xfd92064 8" }, +}; + +static const struct dcc_link_config shikra_link_configs[] = { + { + .link_list = 2, + .entries = shikra_dcc_entries_ll2, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll2), + }, + { + .link_list = 3, + .entries = shikra_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll3), + }, +}; + +static const struct dcc_config shikra_config = { + .lists = shikra_link_configs, + .num_lists = ARRAY_SIZE(shikra_link_configs), +}; + +static const struct dcc_pdata shikra_pdata = { + .base = 0x080ff000, + .size = 0x00001000, + .ram_base = 0x08086000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x3, + .config = &shikra_config, +}; + +#endif /* _QCOM_DCC_SHIKRA_CONFIG_H */ From cbdd4bbfa24a682d76769d4c1c66bb67b262ae4d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 20 May 2026 16:26:37 +0800 Subject: [PATCH 0030/1058] QCLINUX: memory-dump: add memory dump table for Shikra Add memory dump table configuration to enable memory dump function on Shikra platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0845aa152dc2f..fb9d4dc0dceab 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -355,6 +355,37 @@ static const struct dump_item hamoa_items[] = { { ETFSWAO_REG, 0x1000, "etfswao-reg" }, }; +static const struct dump_item shikra_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C0_SCANDUMP, 0x10000, "c0-scandump" }, + { C100_SCANDUMP, 0x10000, "c100-scandump" }, + { C200_SCANDUMP, 0x10000, "c200-scandump" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { L1_ICACHE0, 0x8900, "l1-icache0" }, + { L1_ICACHE100, 0x8900, "l1-icache100" }, + { L1_ICACHE200, 0x8900, "l1-icache200" }, + { L1_ICACHE300, 0x8900, "l1-icache300" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L2_TLB0, 0x2100, "l2-tlb0" }, + { L2_TLB100, 0x2100, "l2-tlb100" }, + { L2_TLB200, 0x2100, "l2-tlb200" }, + { L2_TLB300, 0x2100, "l2-tlb300" }, + { RPM_SW, 0x30000, "rpm-sw" }, + { PMIC, 0x40000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_LPASS, 0x8000, "etf-lpass" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -397,6 +428,13 @@ static const struct dump_table hamoa_dump_table = { .imem_size = 0x8, }; +static const struct dump_table shikra_dump_table = { + .items = shikra_items, + .num_of_items = ARRAY_SIZE(shikra_items), + .imem_base = 0xc11e010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -486,6 +524,14 @@ static int __init mem_dump_dev_init(void) goto fail; break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(mem_dump_pdev, + &shikra_dump_table, sizeof(shikra_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); ret = -EINVAL; From 679dd64f3311d1dc2a168ede579157c314b93f7e Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Mon, 2 Feb 2026 14:30:57 +0800 Subject: [PATCH 0031/1058] FROMLIST: wifi: ath12k: fix incorrect channel survey index A wrong channel survey index was introduced in ath12k_mac_op_get_survey by [1], which can cause ACS to fail. The index is decremented before being used, resulting in an incorrect value when accessing the channel survey data. Fix the index handling to ensure the correct survey entry is used and avoid ACS failures. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Fixes: 4f242b1d6996 ("wifi: ath12k: support get_survey mac op for single wiphy") # [1] Signed-off-by: Yingying Tang --- drivers/net/wireless/ath/ath12k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index af354bef5c0d7..6bc7c8c994a51 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -13584,6 +13584,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, struct ath12k *ar; struct ieee80211_supported_band *sband; struct survey_info *ar_survey; + int orig_idx = idx; lockdep_assert_wiphy(hw->wiphy); @@ -13618,7 +13619,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, return -ENOENT; } - ar_survey = &ar->survey[idx]; + ar_survey = &ar->survey[orig_idx]; ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]); From e61a3fe63d264ac1412539e34d33fb9dd4c1078f Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Sun, 12 Apr 2026 21:23:17 +0800 Subject: [PATCH 0032/1058] FROMLIST: wifi: ath12k: fix TLV32 length mask HAL_TLV_HDR_LEN was using the wrong bitmask; fix it to cover bits [21:10]. Also drop HAL_SRNG_TLV_HDR_{TAG,LEN} and use the generic TLV header bit definitions for TLV32/TLV64 encode/decode to avoid redundant macros. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260509025819.1641630-2-miaoqing.pan@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/hal.c | 8 ++++---- drivers/net/wireless/ath/ath12k/hal.h | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c index a164563fff289..f03817b2fbc52 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -828,8 +828,8 @@ void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len) { struct hal_tlv_64_hdr *tlv64 = tlv; - tlv64->tl = le64_encode_bits(tag, HAL_TLV_HDR_TAG) | - le64_encode_bits(len, HAL_TLV_HDR_LEN); + tlv64->tl = le64_encode_bits(tag, HAL_TLV_64_HDR_TAG) | + le64_encode_bits(len, HAL_TLV_64_HDR_LEN); return tlv64->value; } @@ -851,7 +851,7 @@ u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc) struct hal_tlv_64_hdr *tlv64 = tlv; u16 tag; - tag = le64_get_bits(tlv64->tl, HAL_SRNG_TLV_HDR_TAG); + tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG); *desc = tlv64->value; return tag; @@ -863,7 +863,7 @@ u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc) struct hal_tlv_hdr *tlv32 = tlv; u16 tag; - tag = le32_get_bits(tlv32->tl, HAL_SRNG_TLV_HDR_TAG); + tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG); *desc = tlv32->value; return tag; diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 21c551d8b2481..3ee49d93e24a0 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -1444,7 +1444,7 @@ struct hal_ops { }; #define HAL_TLV_HDR_TAG GENMASK(9, 1) -#define HAL_TLV_HDR_LEN GENMASK(25, 10) +#define HAL_TLV_HDR_LEN GENMASK(21, 10) #define HAL_TLV_USR_ID GENMASK(31, 26) #define HAL_TLV_ALIGN 4 @@ -1464,9 +1464,6 @@ struct hal_tlv_64_hdr { u8 value[]; } __packed; -#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1) -#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10) - dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab, struct hal_srng *srng); dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab, From 0934208353b2b4d52d6cb9c7be9d8eb62cd6e87a Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 17 Apr 2026 15:25:55 +0800 Subject: [PATCH 0033/1058] FROMLIST: wifi: ath12k: refactor HAL TLV32/64 decode helpers Change TLV decode helpers to return the TLV value pointer and optionally decode tag/len/usrid via out parameters. This allows reusing the helpers for DP monitor RX status header TLV parsing and avoids duplicated header decoding in callers. No functional change intended. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260509025819.1641630-3-miaoqing.pan@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/hal.c | 26 ++++++++++++------- drivers/net/wireless/ath/ath12k/hal.h | 4 +-- .../wireless/ath/ath12k/wifi7/hal_qcc2072.c | 2 +- .../wireless/ath/ath12k/wifi7/hal_qcn9274.c | 11 +++++++- .../wireless/ath/ath12k/wifi7/hal_wcn7850.c | 11 +++++++- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c index f03817b2fbc52..d940f83cd92fb 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -846,26 +846,32 @@ void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len) } EXPORT_SYMBOL(ath12k_hal_encode_tlv32_hdr); -u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc) +void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid) { struct hal_tlv_64_hdr *tlv64 = tlv; - u16 tag; - tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG); - *desc = tlv64->value; + if (tag) + *tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG); + if (len) + *len = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_LEN); + if (usrid) + *usrid = le64_get_bits(tlv64->tl, HAL_TLV_64_USR_ID); - return tag; + return tlv64->value; } EXPORT_SYMBOL(ath12k_hal_decode_tlv64_hdr); -u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc) +void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid) { struct hal_tlv_hdr *tlv32 = tlv; - u16 tag; - tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG); - *desc = tlv32->value; + if (tag) + *tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG); + if (len) + *len = le32_get_bits(tlv32->tl, HAL_TLV_HDR_LEN); + if (usrid) + *usrid = le32_get_bits(tlv32->tl, HAL_TLV_USR_ID); - return tag; + return tlv32->value; } EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr); diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 3ee49d93e24a0..d141c516c97fa 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -1553,6 +1553,6 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc, u8 *rbm, u32 *msdu_cnt); void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len); void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len); -u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc); -u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc); +void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); +void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); #endif diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c index 8cebb229ebed8..6383d69656252 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c @@ -455,7 +455,7 @@ static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcc2072(void *tlv, void **desc) struct hal_reo_get_queue_stats_status_qcc2072 *status_tlv; u16 tag; - tag = ath12k_hal_decode_tlv32_hdr(tlv, (void **)&status_tlv); + status_tlv = ath12k_hal_decode_tlv32_hdr(tlv, &tag, NULL, NULL); /* * actual desc of REO status entry starts after tlv32_padding, * see hal_reo_get_queue_stats_status_qcc2072 diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c index 9d5180ef83b48..156a861e021de 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c @@ -950,6 +950,15 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcn9274(rx_desc); } +static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcn9274(void *tlv, void **desc) +{ + u16 tag; + + *desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL); + + return tag; +} + const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN | @@ -1138,5 +1147,5 @@ const struct hal_ops hal_qcn9274_ops = { .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get, .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, - .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcn9274, }; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c index efbbc1cbd3e42..1ae4ff9b94486 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c @@ -756,6 +756,15 @@ int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal) return 0; } +static u16 ath12k_hal_reo_status_dec_tlv_hdr_wcn7850(void *tlv, void **desc) +{ + u16 tag; + + *desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL); + + return tag; +} + const struct ath12k_hal_tcl_to_wbm_rbm_map ath12k_hal_tcl_to_wbm_rbm_map_wcn7850[DP_TCL_NUM_RING_MAX] = { { @@ -821,5 +830,5 @@ const struct hal_ops hal_wcn7850_ops = { .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get, .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, - .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_wcn7850, }; From 0af366772377897522f3600b463765b301a68323 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 17 Apr 2026 16:25:09 +0800 Subject: [PATCH 0034/1058] FROMLIST: wifi: ath12k: add HAL ops for monitor TLV header decode and alignment Wi-Fi 7 monitor RX status TLV parsing needs to decode TLV headers and advance the pointer with the correct header alignment. Different targets use different TLV header layouts (32-bit vs 64-bit), but the HAL ops for dp_mon RX status header decode and header alignment were not populated for all wifi7 targets. Add dp_mon RX status TLV header decode callbacks and TLV header alignment helpers to the wifi7 HAL ops for QCC2072, QCN9274 and WCN7850. Export helpers to query the required TLV header alignment for 32-bit and 64-bit TLV headers so the caller can align the TLV walk correctly across targets. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260509025819.1641630-4-miaoqing.pan@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/hal.c | 12 ++++++++++++ drivers/net/wireless/ath/ath12k/hal.h | 4 ++++ drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c | 2 ++ drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c | 2 ++ drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c | 2 ++ 5 files changed, 22 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c index d940f83cd92fb..c0c3d2f047ef0 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -875,3 +875,15 @@ void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid) return tlv32->value; } EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr); + +u32 ath12k_hal_get_tlv64_hdr_align(void) +{ + return HAL_TLV_64_ALIGN; +} +EXPORT_SYMBOL(ath12k_hal_get_tlv64_hdr_align); + +u32 ath12k_hal_get_tlv32_hdr_align(void) +{ + return HAL_TLV_ALIGN; +} +EXPORT_SYMBOL(ath12k_hal_get_tlv32_hdr_align); diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index d141c516c97fa..ba2c22fb2982b 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -1441,6 +1441,8 @@ struct hal_ops { u8 *rbm, u32 *msdu_cnt); void *(*reo_cmd_enc_tlv_hdr)(void *tlv, u64 tag, u64 len); u16 (*reo_status_dec_tlv_hdr)(void *tlv, void **desc); + void *(*mon_rx_status_dec_tlv_hdr)(void *tlv, u16 *tag, u16 *len, u16 *usrid); + u32 (*get_tlv_hdr_align)(void); }; #define HAL_TLV_HDR_TAG GENMASK(9, 1) @@ -1555,4 +1557,6 @@ void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len); void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len); void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); +u32 ath12k_hal_get_tlv64_hdr_align(void); +u32 ath12k_hal_get_tlv32_hdr_align(void); #endif diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c index 6383d69656252..7cf00fda996f3 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c @@ -506,6 +506,8 @@ const struct hal_ops hal_qcc2072_ops = { .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv32_hdr, .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcc2072, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv32_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv32_hdr_align, }; u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c index 156a861e021de..052b59265af85 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c @@ -1148,4 +1148,6 @@ const struct hal_ops hal_qcn9274_ops = { .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcn9274, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align, }; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c index 1ae4ff9b94486..61be8443e46ee 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c @@ -831,4 +831,6 @@ const struct hal_ops hal_wcn7850_ops = { .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_wcn7850, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align, }; From 902bea0208507b1d1618f2afb2a945ccac7fe87f Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 17 Apr 2026 20:19:00 +0800 Subject: [PATCH 0035/1058] FROMLIST: wifi: ath12k: add dp_mon support 32-bit TLV headers Wi-Fi 7 monitor status parsing in dp_mon currently assumes a 64-bit TLV header and directly decodes tag/len/userid from struct hal_tlv_64_hdr. On chips using a 32-bit TLV header (e.g. QCC2072), this causes monitor RX status packets to be dropped during TLV parsing. Introduce HAL helpers to decode TLV header fields (tag/len/userid/value) for both 32-bit and 64-bit header layouts. Without changing the actual TLV parsing logic. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260509025819.1641630-5-miaoqing.pan@oss.qualcomm.com/ --- .../net/wireless/ath/ath12k/wifi7/dp_mon.c | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c index 7dd4a49d64d5f..06ca96c3cc7e7 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c @@ -1565,16 +1565,17 @@ ath12k_wifi7_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon, static enum hal_rx_mon_status ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev, struct ath12k_mon_data *pmon, - const struct hal_tlv_64_hdr *tlv) + const void *tlv) { struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info; - const void *tlv_data = tlv->value; - u32 info[7], userid; - u16 tlv_tag, tlv_len; + struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev); + struct ath12k_hal *hal = &ar->ab->hal; + u16 tlv_tag, tlv_len, userid; + void *tlv_data; + u32 info[7]; - tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG); - tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN); - userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID); + tlv_data = hal->ops->mon_rx_status_dec_tlv_hdr((void *)tlv, &tlv_tag, + &tlv_len, &userid); if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) { ath12k_wifi7_dp_mon_parse_eht_sig_hdr(ppdu_info, @@ -2930,11 +2931,12 @@ static enum dp_mon_status_buf_state ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng, struct dp_rxdma_mon_ring *rx_ring) { + struct ath12k_hal *hal = &ab->hal; struct ath12k_skb_rxcb *rxcb; - struct hal_tlv_64_hdr *tlv; struct sk_buff *skb; void *status_desc; dma_addr_t paddr; + u16 tlv_tag; u32 cookie; int buf_id; u8 rbm; @@ -2959,8 +2961,8 @@ ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); - tlv = (struct hal_tlv_64_hdr *)skb->data; - if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE) + hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, NULL, NULL); + if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) return DP_MON_STATUS_NO_DMA; return DP_MON_STATUS_REPLINISH; @@ -2972,39 +2974,38 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *skb) { struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev); - struct hal_tlv_64_hdr *tlv; + struct ath12k_hal *hal = &ar->ab->hal; + u8 *tlv_value, *tlv = skb->data; struct ath12k_skb_rxcb *rxcb; enum hal_rx_mon_status hal_status; u16 tlv_tag, tlv_len; - u8 *ptr = skb->data; + u32 tlv_hdr_len; + + tlv_hdr_len = hal->ops->get_tlv_hdr_align(); do { - tlv = (struct hal_tlv_64_hdr *)ptr; - tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG); + tlv_value = hal->ops->mon_rx_status_dec_tlv_hdr(tlv, &tlv_tag, + &tlv_len, NULL); /* The actual length of PPDU_END is the combined length of many PHY * TLVs that follow. Skip the TLV header and * rx_rxpcu_classification_overview that follows the header to get to * next TLV. */ - if (tlv_tag == HAL_RX_PPDU_END) tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview); - else - tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN); hal_status = ath12k_wifi7_dp_mon_rx_parse_status_tlv(dp_pdev, pmon, tlv); if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable && ath12k_wifi7_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status, - tlv->value)) + tlv_value)) return HAL_RX_MON_STATUS_PPDU_DONE; - ptr += sizeof(*tlv) + tlv_len; - ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN); + tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len); - if ((ptr - skb->data) > skb->len) + if ((tlv - skb->data) > skb->len) break; } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) || @@ -3056,15 +3057,16 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id, int buf_id, srng_id, num_buffs_reaped = 0; enum dp_mon_status_buf_state reap_status; struct dp_rxdma_mon_ring *rx_ring; + struct ath12k_hal *hal = &ab->hal; struct ath12k_mon_data *pmon; struct ath12k_skb_rxcb *rxcb; - struct hal_tlv_64_hdr *tlv; void *rx_mon_status_desc; struct hal_srng *srng; struct ath12k_dp *dp; struct sk_buff *skb; struct ath12k *ar; dma_addr_t paddr; + u16 tlv_tag; u32 cookie; u8 rbm; @@ -3109,14 +3111,13 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); - tlv = (struct hal_tlv_64_hdr *)skb->data; - if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != - HAL_RX_STATUS_BUFFER_DONE) { + hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, + NULL, NULL); + if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) { pmon->buf_state = DP_MON_STATUS_NO_DMA; ath12k_warn(ab, - "mon status DONE not set %llx, buf_id %d\n", - le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG), - buf_id); + "mon status DONE not set %x, buf_id %d\n", + tlv_tag, buf_id); /* RxDMA status done bit might not be set even * though tp is moved by HW. */ From 6e963c5fec3baa47be24e69f66314e597284f91d Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Sun, 12 Apr 2026 21:21:46 +0800 Subject: [PATCH 0036/1058] FROMLIST: wifi: ath12k: tighten RX monitor TLV bounds check Validate the pointer to the next RX monitor TLV more strictly by ensuring that at least a full TLV header is available within the status buffer before continuing TLV parsing. Prevent potential out-of-bounds access when handling malformed or truncated RX monitor status data. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260509025819.1641630-6-miaoqing.pan@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c index 06ca96c3cc7e7..c84c42a3d3774 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c @@ -3005,9 +3005,9 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev, tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len); - if ((tlv - skb->data) > skb->len) + if (unlikely(tlv - skb->data > skb->len || + skb->len - (tlv - skb->data) < tlv_hdr_len)) break; - } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) || (hal_status == HAL_RX_MON_STATUS_BUF_ADDR) || (hal_status == HAL_RX_MON_STATUS_MPDU_START) || From 903fd2b553d5dcd9df11171c849e7919d0943bc3 Mon Sep 17 00:00:00 2001 From: Hangtian Zhu Date: Tue, 12 May 2026 10:17:08 +0800 Subject: [PATCH 0037/1058] FROMLIST: genirq: export irq_can_set_affinity() for module drivers Export irq_can_set_affinity() for loadable drivers that need a runtime check for IRQ affinity capability. In hierarchical IRQ setups where the effective irqchip path lacks .irq_set_affinity(), drivers may need to switch to a fallback policy. Without this export, module drivers cannot use the core helper and have to open-code equivalent checks. Signed-off-by: Hangtian Zhu Link: https://lore.kernel.org/all/20260519011627.713068-1-hangtian.zhu@oss.qualcomm.com/ --- kernel/irq/manage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 7eb07e3bdb4c2..f73fda08417ab 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -171,6 +171,7 @@ int irq_can_set_affinity(unsigned int irq) { return __irq_can_set_affinity(irq_to_desc(irq)); } +EXPORT_SYMBOL_GPL(irq_can_set_affinity); /** * irq_can_set_affinity_usr - Check if affinity of a irq can be set from user space From e16f0fa91facfd45085620625314012527502294 Mon Sep 17 00:00:00 2001 From: Hangtian Zhu Date: Tue, 12 May 2026 10:17:08 +0800 Subject: [PATCH 0038/1058] FROMLIST: wifi: ath12k: enable threaded NAPI when DP IRQ affinity is unavailable Determine threaded NAPI policy from runtime IRQ capability of the DP MSI IRQ. If irq_can_set_affinity() reports that affinity cannot be set, enable threaded NAPI for DP interrupt groups so datapath processing is not constrained by a single-CPU softirq context. On RB3Gen2, where IRQ affinity is unavailable in the effective IRQ path, EHT160 UDP downlink throughput improved from 802 Mbps to 2.58 Gbps after enabling threaded NAPI. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00074-QCACOLSWPL_V1_TO_SILICONZ-1 Signed-off-by: Hangtian Zhu Link: https://lore.kernel.org/all/20260519011627.713068-1-hangtian.zhu@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/pci.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index d9a22d6afbb02..6073157fcedb7 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -537,6 +538,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) int i, j, n, ret, num_vectors = 0; u32 user_base_data = 0, base_vector = 0, base_idx; struct ath12k_ext_irq_grp *irq_grp; + bool threaded_napi = false; + int irq; base_idx = ATH12K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; ret = ath12k_pci_get_user_msi_assignment(ab, "DP", @@ -546,6 +549,10 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) if (ret < 0) return ret; + irq = ath12k_pci_get_msi_irq(ab->dev, base_vector); + if (irq >= 0) + threaded_napi = !irq_can_set_affinity(irq); + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { irq_grp = &ab->ext_irq_grp[i]; u32 num_irq = 0; @@ -560,6 +567,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi, ath12k_pci_ext_grp_napi_poll); + if (threaded_napi) + netif_threaded_enable(irq_grp->napi_ndev); if (ab->hw_params->ring_mask->tx[i] || ab->hw_params->ring_mask->rx[i] || @@ -578,7 +587,7 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) for (j = 0; j < irq_grp->num_irq; j++) { int irq_idx = irq_grp->irqs[j]; int vector = (i % num_vectors) + base_vector; - int irq = ath12k_pci_get_msi_irq(ab->dev, vector); + irq = ath12k_pci_get_msi_irq(ab->dev, vector); ab->irq_num[irq_idx] = irq; From 522316e1302bbe70f416badc97b98e9db2b84768 Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Fri, 27 Mar 2026 21:10:11 +0800 Subject: [PATCH 0039/1058] wifi: ath12k: change MAC buffer ring size to 4096 For WCN7850, MAC buffer ring size is updated to 2048 in 955df16f2a4c3 ("wifi: ath12k: change MAC buffer ring size to 2048") to increase peak throughput. But during the RX process, a phenomenon can still be observed where the throughput drops by about 30% from its peak value and then recovers, and this behavior repeats during RX. After increasing MAC buffer ring size to 4096, the data rate drop has gone. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Yingying Tang --- drivers/net/wireless/ath/ath12k/dp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index f8cfc7bb29dd7..6596089d41688 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -205,7 +205,7 @@ struct ath12k_pdev_dp { #define DP_REO_CMD_RING_SIZE 256 #define DP_REO_STATUS_RING_SIZE 2048 #define DP_RXDMA_BUF_RING_SIZE 4096 -#define DP_RX_MAC_BUF_RING_SIZE 2048 +#define DP_RX_MAC_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 #define DP_RXDMA_ERR_DST_RING_SIZE 1024 #define DP_RXDMA_MON_STATUS_RING_SIZE 1024 From 060c95ddaa8cd3125b95916c480047c45b317d6f Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 10 Jun 2026 08:46:48 +0530 Subject: [PATCH 0040/1058] wifi: ath12k: Fix low MLO RX throughput on WCN7850 Commit [1] introduced a regression causing severely degraded MLO RX throughput on WCN7850. On WCN7850, there is only a single ar instance, but MLO uses two link IDs. ath12k_dp_peer->hw_links[] is indexed using ar->hw_link_id, which causes both MLO link IDs to be stored at the same index. As a result, an incorrect link ID is assigned to MSDUs in ath12k_dp_rx_deliver_msdu(), leading to severe MLO RX throughput loss. Different chipsets identify the per-MSDU link differently: - On QCN9274 / IPQ5332, the host owns multiple ar instances and the per-MSDU hw_link_id from the RX descriptor maps cleanly through dp_peer->hw_links[hw_link_id] to the IEEE link_id. - On single-ar chipsets like WCN7850 / QCC2072, there is only one ar instance for both MLO links, so dp_peer->hw_links[] has just one valid slot and cannot be used to distinguish the two links. To resolve the link, walk dp_peer->link_peers[] and match by rxcb->peer_id, which on the link_peer side identifies the link peer for the MSDU. Add a new hw_op set_rx_link_id() so each chipset resolves the link on the RX fast path using whatever signal it actually has, and let the op itself decide whether to populate rx_status::link_valid and rx_status::link_id: QCN9274 / IPQ5332 : always derive link_id from dp_peer->hw_links[rxcb->hw_link_id] and set link_valid. WCN7850 / QCC2072 : walk the link_peers[] of dp_peer to find the link_peer whose peer_id matches rxcb->peer_id, and set link_valid only when a match is found. Otherwise leave link_valid clear so that mac80211 can fall back to its own link resolution path (via addr2 / deflink). For WCN7850 / QCC2072, walking dp_peer->link_peers[] is bounded by the number of links actually populated, so introduce a link_peers_map bitmap (unsigned long) in struct ath12k_dp_peer that tracks populated slots and use for_each_set_bit() to iterate. Non-MLO clients hit one slot, current MLO clients hit two; the full ATH12K_NUM_MAX_LINKS array is never scanned. The bitmap is maintained with WRITE_ONCE() on the write side (under dp_hw->peer_lock) paired with READ_ONCE() on both the lockless RX read side and the write-side RMW for KCSAN correctness. Also guard the dp_peer dereference in ath12k_mac_peer_cleanup_all() with a NULL check, since peer->dp_peer can be NULL for self-peers or peers not yet fully assigned, the pre-existing rcu_assign_pointer() call there had the same latent issue. This restores the correct link ID on WCN7850 without changing the QCN9274 / IPQ5332 data path, which keeps its O(1) hw_links[] indexing. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Fixes: 11157e0910fd ("wifi: ath12k: Use ath12k_dp_peer in per packet Tx & Rx paths") # [1] Signed-off-by: Yingying Tang --- drivers/net/wireless/ath/ath12k/dp_peer.c | 4 +++ drivers/net/wireless/ath/ath12k/dp_peer.h | 1 + drivers/net/wireless/ath/ath12k/dp_rx.c | 7 ++-- drivers/net/wireless/ath/ath12k/hw.h | 16 +++++++++ drivers/net/wireless/ath/ath12k/mac.c | 10 ++++-- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 33 +++++++++++++++++++ drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 6 ++++ drivers/net/wireless/ath/ath12k/wifi7/hw.c | 3 ++ 8 files changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 47d009a0d61fe..2660b4c7449be 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -570,6 +570,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) | BIT(peer->link_id)); rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer); @@ -632,6 +634,8 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index f5067e66f1e18..7c9709bf717b4 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -140,6 +140,7 @@ struct ath12k_dp_peer { /* Info used in MMIC verification of * RX fragments */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; + unsigned long link_peers_map; struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1]; struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 06e74124e57eb..8fa0e90b45316 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -1384,10 +1384,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc pubsta = peer ? peer->sta : NULL; - if (pubsta && pubsta->valid_links) { - status->link_valid = 1; - status->link_id = peer->hw_links[rxcb->hw_link_id]; - } + status->link_valid = 0; + if (pubsta && pubsta->valid_links) + ath12k_hw_set_rx_link_id(dp->hw_params, peer, rxcb, status); ath12k_dbg(dp->ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index d135b29363788..86fb8b7196135 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -13,6 +13,10 @@ #include "wmi.h" #include "hal.h" +struct ath12k_dp_peer; +struct ath12k_skb_rxcb; +struct ieee80211_rx_status; + /* Target configuration defines */ /* Num VDEVS per radio */ @@ -243,6 +247,9 @@ struct ath12k_hw_ops { bool (*dp_srng_is_tx_comp_ring)(int ring_num); bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif, struct ieee80211_mgmt *mgmt); + void (*set_rx_link_id)(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); }; static inline @@ -273,6 +280,15 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw, return 0; } +static inline void ath12k_hw_set_rx_link_id(const struct ath12k_hw_params *hw, + struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + if (hw->hw_ops->set_rx_link_id) + hw->hw_ops->set_rx_link_id(dp_peer, rxcb, status); +} + struct ath12k_fw_ie { __le32 id; __le32 len; diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 6bc7c8c994a51..04d78dd64ac53 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1238,9 +1238,13 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) /* cleanup dp peer */ spin_lock_bh(&dp_hw->peer_lock); dp_peer = peer->dp_peer; - peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); - rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); - rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + if (dp_peer) { + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + } spin_unlock_bh(&dp_hw->peer_lock); ath12k_dp_link_peer_rhash_delete(dp, peer); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index cb9dd8cb28b67..95d87dd67872f 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -5,6 +5,7 @@ */ #include "dp_rx.h" +#include "../dp_peer.h" #include "../dp_tx.h" #include "../peer.h" #include "hal_qcn9274.h" @@ -2315,3 +2316,35 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, return tlv_tag == HAL_RX_MPDU_START; } + +void +ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + status->link_valid = 1; + status->link_id = dp_peer->hw_links[rxcb->hw_link_id]; +} + +void +ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + struct ath12k_dp_link_peer *link_peer; + unsigned long links_map; + int i; + + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "ath12k set rx link id called without rcu lock"); + + links_map = READ_ONCE(dp_peer->link_peers_map); + for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) { + link_peer = rcu_dereference(dp_peer->link_peers[i]); + if (link_peer && link_peer->peer_id == rxcb->peer_id) { + status->link_valid = 1; + status->link_id = link_peer->link_id; + return; + } + } +} diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h index 8aa79faf567fd..1d3a4788a2dd9 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h @@ -57,4 +57,10 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, struct hal_rx_desc *rx_desc); int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab, struct ath12k_dp_rx_tid_rxq *rx_tid); +void ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); +void ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); #endif diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index 3d59fa452ec03..d9fdd2fc82986 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -158,6 +158,7 @@ static const struct ath12k_hw_ops qcn9274_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_qcn9274, }; static const struct ath12k_hw_ops wcn7850_ops = { @@ -168,6 +169,7 @@ static const struct ath12k_hw_ops wcn7850_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, }; static const struct ath12k_hw_ops qcc2072_ops = { @@ -178,6 +180,7 @@ static const struct ath12k_hw_ops qcc2072_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, }; #define ATH12K_TX_RING_MASK_0 0x1 From 5f5a3a067417fe5479d03b68f0248343b9a573e3 Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Fri, 22 May 2026 13:47:45 +0800 Subject: [PATCH 0041/1058] FROMLIST: Revert "wifi: ath12k: add panic handler" This reverts commit 809055628bce824b7fe18331abb65e44d02b0ecf. Call trace: rcu_note_context_switch+0x4c4/0x508 (P) __schedule+0xbc/0x1204 schedule+0x34/0x110 schedule_timeout+0x84/0x11c __mhi_device_get_sync+0x164/0x228 [mhi] mhi_device_get_sync+0x1c/0x3c [mhi] ath12k_wifi7_pci_bus_wake_up+0x20/0x2c [ath12k_wifi7] ath12k_pci_read32+0x58/0x350 [ath12k] ath12k_pci_clear_dbg_registers+0x28/0xb8 [ath12k] ath12k_pci_panic_handler+0x20/0x44 [ath12k] ath12k_core_panic_handler+0x28/0x3c [ath12k] notifier_call_chain+0x78/0x1c0 atomic_notifier_call_chain+0x3c/0x5c ath12k_core_panic_handler() is invoked via atomic_notifier_call_chain(), which runs inside an RCU read-side critical section. The current code calls ath12k_pci_sw_reset() synchronously from this context, which eventually reaches mhi_device_get_sync() and schedule_timeout(), triggering a voluntary context switch within RCU. Revert change "wifi: ath12k: add panic handler" to avoid this issue. Tested-on: WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Link: https://lore.kernel.org/all/20260612032332.2278338-1-yingying.tang@oss.qualcomm.com/ Signed-off-by: Yingying Tang --- drivers/net/wireless/ath/ath12k/core.c | 33 +------------------------- drivers/net/wireless/ath/ath12k/core.h | 3 --- drivers/net/wireless/ath/ath12k/hif.h | 9 ------- drivers/net/wireless/ath/ath12k/pci.c | 8 ------- 4 files changed, 1 insertion(+), 52 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 742d4fd1b598c..4bbfaaa446ec0 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1793,29 +1793,6 @@ int ath12k_core_pre_init(struct ath12k_base *ab) return 0; } -static int ath12k_core_panic_handler(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct ath12k_base *ab = container_of(nb, struct ath12k_base, - panic_nb); - - return ath12k_hif_panic_handler(ab); -} - -static int ath12k_core_panic_notifier_register(struct ath12k_base *ab) -{ - ab->panic_nb.notifier_call = ath12k_core_panic_handler; - - return atomic_notifier_chain_register(&panic_notifier_list, - &ab->panic_nb); -} - -static void ath12k_core_panic_notifier_unregister(struct ath12k_base *ab) -{ - atomic_notifier_chain_unregister(&panic_notifier_list, - &ab->panic_nb); -} - static inline bool ath12k_core_hw_group_create_ready(struct ath12k_hw_group *ag) { @@ -2231,18 +2208,13 @@ int ath12k_core_init(struct ath12k_base *ab) struct ath12k_hw_group *ag; int ret; - ret = ath12k_core_panic_notifier_register(ab); - if (ret) - ath12k_warn(ab, "failed to register panic handler: %d\n", ret); - mutex_lock(&ath12k_hw_group_mutex); ag = ath12k_core_hw_group_assign(ab); if (!ag) { mutex_unlock(&ath12k_hw_group_mutex); ath12k_warn(ab, "unable to get hw group\n"); - ret = -ENODEV; - goto err_unregister_notifier; + return -ENODEV; } mutex_unlock(&ath12k_hw_group_mutex); @@ -2267,8 +2239,6 @@ int ath12k_core_init(struct ath12k_base *ab) err_unassign_hw_group: ath12k_core_hw_group_unassign(ab); -err_unregister_notifier: - ath12k_core_panic_notifier_unregister(ab); return ret; } @@ -2277,7 +2247,6 @@ void ath12k_core_deinit(struct ath12k_base *ab) { ath12k_core_hw_group_destroy(ab->ag); ath12k_core_hw_group_unassign(ab); - ath12k_core_panic_notifier_unregister(ab); } void ath12k_core_free(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index fc5127b5c1a37..d41b8a556ea2c 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -1138,8 +1137,6 @@ struct ath12k_base { #endif /* CONFIG_ACPI */ - struct notifier_block panic_nb; - struct ath12k_hw_group *ag; struct ath12k_wsi_info wsi_info; enum ath12k_firmware_mode fw_mode; diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h index 4de8667690e91..aecdb0c5f2858 100644 --- a/drivers/net/wireless/ath/ath12k/hif.h +++ b/drivers/net/wireless/ath/ath12k/hif.h @@ -30,7 +30,6 @@ struct ath12k_hif_ops { void (*ce_irq_enable)(struct ath12k_base *ab); void (*ce_irq_disable)(struct ath12k_base *ab); void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx); - int (*panic_handler)(struct ath12k_base *ab); void (*coredump_download)(struct ath12k_base *ab); }; @@ -149,14 +148,6 @@ static inline void ath12k_hif_power_down(struct ath12k_base *ab, bool is_suspend ab->hif.ops->power_down(ab, is_suspend); } -static inline int ath12k_hif_panic_handler(struct ath12k_base *ab) -{ - if (!ab->hif.ops->panic_handler) - return NOTIFY_DONE; - - return ab->hif.ops->panic_handler(ab); -} - static inline void ath12k_hif_coredump_download(struct ath12k_base *ab) { if (ab->hif.ops->coredump_download) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 6073157fcedb7..45704c8264894 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1478,13 +1478,6 @@ void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend) ath12k_pci_sw_reset(ab_pci->ab, false); } -static int ath12k_pci_panic_handler(struct ath12k_base *ab) -{ - ath12k_pci_sw_reset(ab, false); - - return NOTIFY_OK; -} - static const struct ath12k_hif_ops ath12k_pci_hif_ops = { .start = ath12k_pci_start, .stop = ath12k_pci_stop, @@ -1502,7 +1495,6 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = { .ce_irq_enable = ath12k_pci_hif_ce_irq_enable, .ce_irq_disable = ath12k_pci_hif_ce_irq_disable, .get_ce_msi_idx = ath12k_pci_get_ce_msi_idx, - .panic_handler = ath12k_pci_panic_handler, #ifdef CONFIG_ATH12K_COREDUMP .coredump_download = ath12k_pci_coredump_download, #endif From 9325222d9c95fa1a4f30ca98251742bcab9ed335 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 8 Sep 2025 09:50:25 +0800 Subject: [PATCH 0042/1058] wifi: ath12k: Fix missing station power save configuration Commit afbab6e4e88d ("wifi: ath12k: modify ath12k_mac_op_bss_info_changed() for MLO") replaced the bss_info_changed() callback with vif_cfg_changed() and link_info_changed() to support Multi-Link Operation (MLO). As a result, the station power save configuration is no longer correctly applied in ath12k_mac_bss_info_changed(). Move the handling of 'BSS_CHANGED_PS' into ath12k_mac_op_vif_cfg_changed() to align with the updated callback structure introduced for MLO, ensuring proper power-save behavior for station interfaces. Tested-on: WCN7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00011-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 Fixes: afbab6e4e88d ("wifi: ath12k: modify ath12k_mac_op_bss_info_changed() for MLO") Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/all/20250908015025.1301398-1-miaoqing.pan@oss.qualcomm.com/ Signed-off-by: Daizhuang Bai --- drivers/net/wireless/ath/ath12k/mac.c | 124 ++++++++++++++------------ 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 04d78dd64ac53..4bbbaf4a99c60 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4365,12 +4365,68 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif, return ret; } +static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) +{ + struct ath12k *ar = arvif->ar; + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; + enum wmi_sta_powersave_param param; + struct ieee80211_bss_conf *info; + enum wmi_sta_ps_mode psmode; + int ret; + int timeout; + bool enable_ps; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + enable_ps = arvif->ahvif->ps; + if (enable_ps) { + psmode = WMI_STA_PS_MODE_ENABLED; + param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + + timeout = conf->dynamic_ps_timeout; + if (timeout == 0) { + info = ath12k_mac_get_link_bss_conf(arvif); + if (!info) { + ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", + vif->addr, arvif->link_id); + return; + } + + /* firmware doesn't like 0 */ + timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; + } + + ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, + timeout); + if (ret) { + ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", + arvif->vdev_id, ret); + return; + } + } else { + psmode = WMI_STA_PS_MODE_DISABLED; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", + arvif->vdev_id, psmode ? "enable" : "disable"); + + ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); + if (ret) + ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", + psmode, arvif->vdev_id, ret); +} + void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed) { struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); unsigned long links = ahvif->links_map; + struct ieee80211_vif_cfg *vif_cfg; struct ieee80211_bss_conf *info; struct ath12k_link_vif *arvif; struct ieee80211_sta *sta; @@ -4434,63 +4490,26 @@ void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, } } } -} -EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); - -static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) -{ - struct ath12k *ar = arvif->ar; - struct ieee80211_vif *vif = arvif->ahvif->vif; - struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; - enum wmi_sta_powersave_param param; - struct ieee80211_bss_conf *info; - enum wmi_sta_ps_mode psmode; - int ret; - int timeout; - bool enable_ps; - lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + if (changed & BSS_CHANGED_PS) { + links = ahvif->links_map; + vif_cfg = &vif->cfg; - if (vif->type != NL80211_IFTYPE_STATION) - return; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->ar) + continue; - enable_ps = arvif->ahvif->ps; - if (enable_ps) { - psmode = WMI_STA_PS_MODE_ENABLED; - param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + ar = arvif->ar; - timeout = conf->dynamic_ps_timeout; - if (timeout == 0) { - info = ath12k_mac_get_link_bss_conf(arvif); - if (!info) { - ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", - vif->addr, arvif->link_id); - return; + if (ar->ab->hw_params->supports_sta_ps) { + ahvif->ps = vif_cfg->ps; + ath12k_mac_vif_setup_ps(arvif); } - - /* firmware doesn't like 0 */ - timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; - } - - ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, - timeout); - if (ret) { - ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", - arvif->vdev_id, ret); - return; } - } else { - psmode = WMI_STA_PS_MODE_DISABLED; } - - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", - arvif->vdev_id, psmode ? "enable" : "disable"); - - ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); - if (ret) - ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", - psmode, arvif->vdev_id, ret); } +EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); static bool ath12k_mac_supports_tpc(struct ath12k *ar, struct ath12k_vif *ahvif, const struct cfg80211_chan_def *chandef) @@ -4695,7 +4714,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, { struct ath12k_vif *ahvif = arvif->ahvif; struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); - struct ieee80211_vif_cfg *vif_cfg = &vif->cfg; struct ath12k_link_vif *tx_arvif; struct cfg80211_chan_def def; u32 param_id, param_value; @@ -5033,12 +5051,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } ath12k_mac_fils_discovery(arvif, info); - - if (changed & BSS_CHANGED_PS && - ar->ab->hw_params->supports_sta_ps) { - ahvif->ps = vif_cfg->ps; - ath12k_mac_vif_setup_ps(arvif); - } } static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif, From 3c8e3d66df402846c613c9e7481cecf8901d44ed Mon Sep 17 00:00:00 2001 From: Gaole Zhang Date: Fri, 24 Apr 2026 14:52:11 +0800 Subject: [PATCH 0043/1058] FROMLIST: wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set unconditionally even when ath11k_core_qmi_firmware_ready() fails. This leaves the driver in an inconsistent state where initialization is considered complete although the firmware ready handling did not finish successfully. During the subsequent SSR, the driver enters the restart path based on this incorrect state and dereferences uninitialized srng members, resulting in a NULL pointer dereference. Call trace: ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] ath11k_core_restart+0x40/0x168 [ath11k] Fix this by: - skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set - setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds - setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling on error Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") Signed-off-by: Gaole Zhang Link: https://lore.kernel.org/linux-wireless/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 410a7ee076a02..7dc07339b9579 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -3294,9 +3294,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); - ath11k_core_qmi_firmware_ready(ab); - set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); - + if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { + ret = ath11k_core_qmi_firmware_ready(ab); + if (ret) { + set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); + break; + } + set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); + } break; case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: break; From 003483d986c57d913b66f624920fa7fce28e4650 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:51 +0800 Subject: [PATCH 0044/1058] FROMLIST: coresight: core: refactor ctcu_get_active_port and make it generic Remove ctcu_get_active_port from CTCU module and add it to the core framework. The port number is crucial for the CTCU device to identify which ETR it serves. With the port number we can correctly get required parameters of the CTCU device in TMC module. Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-1-8fbbf22e8381@oss.qualcomm.com/ Reviewed-by: Mike Leach Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-core.c | 27 +++++++++++++++++++ .../hwtracing/coresight/coresight-ctcu-core.c | 19 +------------ drivers/hwtracing/coresight/coresight-priv.h | 2 ++ 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 6d65c43d574fd..7a7a85acdca0d 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -773,6 +773,33 @@ struct coresight_device *coresight_get_sink(struct coresight_path *path) } EXPORT_SYMBOL_GPL(coresight_get_sink); +/** + * coresight_get_in_port: Find the input port number at @remote where the @csdev + * device is connected to. + * + * @csdev: csdev of the device. + * @remote: csdev of the remote device which is connected to @csdev. + * + * Return: port number upon success or -EINVAL for fail. + */ +int coresight_get_in_port(struct coresight_device *csdev, + struct coresight_device *remote) +{ + struct coresight_platform_data *pdata = remote->pdata; + int i; + + for (i = 0; i < pdata->nr_inconns; ++i) { + if (!pdata->in_conns[i]) + continue; + + if (pdata->in_conns[i]->src_dev == csdev) + return pdata->in_conns[i]->dest_port; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(coresight_get_in_port); + u32 coresight_get_sink_id(struct coresight_device *csdev) { if (!csdev->ea) diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c index 9043cad42f01e..e8720026c9e3f 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c @@ -116,23 +116,6 @@ static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, in return 0; } -/* - * Searching the sink device from helper's view in case there are multiple helper devices - * connected to the sink device. - */ -static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper) -{ - struct coresight_platform_data *pdata = helper->pdata; - int i; - - for (i = 0; i < pdata->nr_inconns; ++i) { - if (pdata->in_conns[i]->src_dev == sink) - return pdata->in_conns[i]->dest_port; - } - - return -EINVAL; -} - static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight_path *path, bool enable) { @@ -145,7 +128,7 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight return -EINVAL; } - port_num = ctcu_get_active_port(sink, csdev); + port_num = coresight_get_in_port(sink, csdev); if (port_num < 0) return -EINVAL; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index dddac946659fc..854c0a3cb080c 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -155,6 +155,8 @@ void coresight_remove_links(struct coresight_device *orig, u32 coresight_get_sink_id(struct coresight_device *csdev); int coresight_path_assign_trace_id(struct coresight_path *path, enum cs_mode mode); +int coresight_get_in_port(struct coresight_device *csdev, + struct coresight_device *remote); #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X) int etm_readl_cp14(u32 off, unsigned int *val); From c6ba413f513df906f6bd901fa499be1efd7bc6dd Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:52 +0800 Subject: [PATCH 0045/1058] FROMLIST: coresight: tmc: add create/clean functions for etr_buf_list Introduce functions for creating and inserting or removing the etr_buf_node to/from the etr_buf_list. The byte-cntr functionality requires two etr_buf to receive trace data. The active etr_buf collects the trace data from source device, while the byte-cntr reading function accesses the deactivated etr_buf after is has been filled and synced, transferring data to the userspace. Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-2-8fbbf22e8381@oss.qualcomm.com/ Reviewed-by: Mike Leach Signed-off-by: Jie Gan --- .../hwtracing/coresight/coresight-tmc-core.c | 1 + .../hwtracing/coresight/coresight-tmc-etr.c | 126 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc.h | 17 +++ 3 files changed, 144 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index bc5a133ada3e3..bc7dd676da473 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -835,6 +835,7 @@ static int __tmc_probe(struct device *dev, struct resource *res) idr_init(&drvdata->idr); mutex_init(&drvdata->idr_mutex); dev_list = "tmc_etr"; + INIT_LIST_HEAD(&drvdata->etr_buf_list); break; case TMC_CONFIG_TYPE_ETF: desc.groups = coresight_etf_groups; diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 361a433e6f0c5..9b3ef73e9cf27 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1918,6 +1918,132 @@ const struct coresight_ops tmc_etr_cs_ops = { .panic_ops = &tmc_etr_sync_ops, }; +/** + * tmc_clean_etr_buf_list - clean the etr_buf_list. + * @drvdata: driver data of the TMC device. + * + * Remove all nodes from @drvdata->etr_buf_list and free their buffers. + * If a node holds the live sysfs_buf and the device is active, the node is + * removed but the buffer is not freed; ownership stays with drvdata->sysfs_buf. + * + * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list + * and must not hold @drvdata->spinlock. The spinlock is taken internally only + * to serialise the @drvdata->sysfs_buf accesses against the ETR sink + * enable/disable paths. Must be called from process context: buffers are freed + * with the lock released. + */ +void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata) +{ + struct etr_buf_node *nd, *next; + unsigned long flags; + + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) { + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (nd->sysfs_buf == drvdata->sysfs_buf) { + if (coresight_get_mode(drvdata->csdev) != CS_MODE_DISABLED) + /* + * The device is still active. Keep the live + * buffer owned by drvdata->sysfs_buf and only + * drop the list's reference to it. + */ + nd->sysfs_buf = NULL; + else + /* Free the buffer below through nd->sysfs_buf */ + drvdata->sysfs_buf = NULL; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + /* Free the buffer (NULL is ignored) and the node out of the lock */ + tmc_etr_free_sysfs_buf(nd->sysfs_buf); + list_del(&nd->link); + kfree(nd); + } +} +EXPORT_SYMBOL_GPL(tmc_clean_etr_buf_list); + +/** + * tmc_create_etr_buf_list - create a list to manage the etr_buf_node. + * @drvdata: driver data of the TMC device. + * @num_nodes: number of nodes want to create with the list. + * + * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list + * and must not hold @drvdata->spinlock. The spinlock is taken internally only + * to serialise the @drvdata->sysfs_buf accesses against the ETR sink + * enable/disable paths. Must be called from process context: buffers and nodes + * are allocated with the lock released. + * + * Return 0 upon success and return the error number if fail. + */ +int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes) +{ + struct etr_buf_node *new_node; + struct etr_buf *sysfs_buf; + unsigned long flags; + int i = 0, ret = 0; + + /* We don't need a list if there is only one node */ + if (num_nodes < 2) + return -EINVAL; + + /* + * We expect that sysfs_buf in drvdata has already been allocated. + * Wrap the live sysfs_buf into the first node so the captured trace + * data is preserved. The list is owned by the caller, so no lock is + * needed to read sysfs_buf or to add the node here. + */ + if (drvdata->sysfs_buf) { + new_node = kzalloc_obj(*new_node, GFP_KERNEL); + if (!new_node) + return -ENOMEM; + + new_node->sysfs_buf = drvdata->sysfs_buf; + new_node->is_free = false; + list_add(&new_node->link, &drvdata->etr_buf_list); + i++; + } + + while (i < num_nodes) { + new_node = kzalloc_obj(*new_node, GFP_KERNEL); + if (!new_node) { + ret = -ENOMEM; + break; + } + + /* Allocate the buffer with the lock released */ + sysfs_buf = tmc_alloc_etr_buf(drvdata, drvdata->size, 0, cpu_to_node(0), NULL); + if (IS_ERR(sysfs_buf)) { + kfree(new_node); + ret = PTR_ERR(sysfs_buf); + break; + } + + new_node->sysfs_buf = sysfs_buf; + /* + * Only the drvdata->sysfs_buf write needs the spinlock, to + * serialise against the ETR sink enable/disable paths. + */ + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + /* We don't have an available sysfs_buf in drvdata, set one up */ + if (!drvdata->sysfs_buf) { + drvdata->sysfs_buf = sysfs_buf; + new_node->is_free = false; + } else { + new_node->is_free = true; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + list_add_tail(&new_node->link, &drvdata->etr_buf_list); + i++; + } + + /* Clean the list if there is an error */ + if (ret) + tmc_clean_etr_buf_list(drvdata); + + return ret; +} +EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list); + int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret = 0; diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 319a354ede9fc..6e994678f9264 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -208,6 +208,19 @@ struct tmc_resrv_buf { s64 len; }; +/** + * @sysfs_buf: Allocated sysfs_buf. + * @is_free: Indicates whether the buffer is free to choose. + * @pos: Offset to the start of the buffer. + * @link: list_head of the node. + */ +struct etr_buf_node { + struct etr_buf *sysfs_buf; + bool is_free; + loff_t pos; + struct list_head link; +}; + /** * struct tmc_drvdata - specifics associated to an TMC component * @atclk: optional clock for the core parts of the TMC. @@ -245,6 +258,7 @@ struct tmc_resrv_buf { * (after crash) by default. * @crash_mdata: Reserved memory for storing tmc crash metadata. * Used by ETR/ETF. + * @etr_buf_list: List that is used to manage allocated etr_buf. */ struct tmc_drvdata { struct clk *atclk; @@ -275,6 +289,7 @@ struct tmc_drvdata { struct etr_buf *perf_buf; struct tmc_resrv_buf resrv_buf; struct tmc_resrv_buf crash_mdata; + struct list_head etr_buf_list; }; struct etr_buf_operations { @@ -447,5 +462,7 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, enum cs_mode mode, struct coresight_path *path); extern const struct attribute_group coresight_etr_group; +void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata); +int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes); #endif From fbb1b16214fc6a5e48aae44923da1d4bc96d001b Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:53 +0800 Subject: [PATCH 0046/1058] FROMLIST: coresight: tmc: introduce tmc_sysfs_ops to wrap sysfs read operations Introduce tmc_sysfs_ops as a wrapper, wrap sysfs read operations, for reading trace data from the TMC buffer. Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-3-8fbbf22e8381@oss.qualcomm.com/ Reviewed-by: Mike Leach Signed-off-by: Jie Gan --- .../hwtracing/coresight/coresight-tmc-core.c | 51 ++++++++----------- drivers/hwtracing/coresight/coresight-tmc.h | 15 ++++++ 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index bc7dd676da473..4b40b692be4d8 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -228,17 +228,10 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) { int ret = 0; - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - ret = tmc_read_prepare_etb(drvdata); - break; - case TMC_CONFIG_TYPE_ETR: - ret = tmc_read_prepare_etr(drvdata); - break; - default: + if (drvdata->sysfs_ops) + ret = drvdata->sysfs_ops->read_prepare(drvdata); + else ret = -EINVAL; - } if (!ret) dev_dbg(&drvdata->csdev->dev, "TMC read start\n"); @@ -250,17 +243,10 @@ static int tmc_read_unprepare(struct tmc_drvdata *drvdata) { int ret = 0; - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - ret = tmc_read_unprepare_etb(drvdata); - break; - case TMC_CONFIG_TYPE_ETR: - ret = tmc_read_unprepare_etr(drvdata); - break; - default: + if (drvdata->sysfs_ops) + ret = drvdata->sysfs_ops->read_unprepare(drvdata); + else ret = -EINVAL; - } if (!ret) dev_dbg(&drvdata->csdev->dev, "TMC read end\n"); @@ -287,15 +273,7 @@ static int tmc_open(struct inode *inode, struct file *file) static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, char **bufpp) { - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp); - case TMC_CONFIG_TYPE_ETR: - return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); - } - - return -EINVAL; + return drvdata->sysfs_ops->get_trace_data(drvdata, pos, len, bufpp); } static ssize_t tmc_read(struct file *file, char __user *data, size_t len, @@ -764,6 +742,18 @@ static void register_crash_dev_interface(struct tmc_drvdata *drvdata, "Valid crash tracedata found\n"); } +static const struct tmc_sysfs_ops etb_sysfs_ops = { + .read_prepare = tmc_read_prepare_etb, + .read_unprepare = tmc_read_unprepare_etb, + .get_trace_data = tmc_etb_get_sysfs_trace, +}; + +static const struct tmc_sysfs_ops etr_sysfs_ops = { + .read_prepare = tmc_read_prepare_etr, + .read_unprepare = tmc_read_unprepare_etr, + .get_trace_data = tmc_etr_get_sysfs_trace, +}; + static int __tmc_probe(struct device *dev, struct resource *res) { int ret = 0; @@ -823,6 +813,7 @@ static int __tmc_probe(struct device *dev, struct resource *res) desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc.ops = &tmc_etb_cs_ops; dev_list = "tmc_etb"; + drvdata->sysfs_ops = &etb_sysfs_ops; break; case TMC_CONFIG_TYPE_ETR: desc.groups = coresight_etr_groups; @@ -835,6 +826,7 @@ static int __tmc_probe(struct device *dev, struct resource *res) idr_init(&drvdata->idr); mutex_init(&drvdata->idr_mutex); dev_list = "tmc_etr"; + drvdata->sysfs_ops = &etr_sysfs_ops; INIT_LIST_HEAD(&drvdata->etr_buf_list); break; case TMC_CONFIG_TYPE_ETF: @@ -844,6 +836,7 @@ static int __tmc_probe(struct device *dev, struct resource *res) desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc.ops = &tmc_etf_cs_ops; dev_list = "tmc_etf"; + drvdata->sysfs_ops = &etb_sysfs_ops; break; default: pr_err("%s: Unsupported TMC config\n", desc.name); diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 6e994678f9264..a14645b04624a 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -259,6 +259,7 @@ struct etr_buf_node { * @crash_mdata: Reserved memory for storing tmc crash metadata. * Used by ETR/ETF. * @etr_buf_list: List that is used to manage allocated etr_buf. + * @sysfs_ops: Read operations for the sysfs mode. */ struct tmc_drvdata { struct clk *atclk; @@ -290,6 +291,20 @@ struct tmc_drvdata { struct tmc_resrv_buf resrv_buf; struct tmc_resrv_buf crash_mdata; struct list_head etr_buf_list; + const struct tmc_sysfs_ops *sysfs_ops; +}; + +/** + * struct tmc_sysfs_ops - read operations for TMC and its helper devices + * @read_prepare: prepare operation. + * @read_unprepare: unprepare operation. + * @get_trace_data: read operation. + */ +struct tmc_sysfs_ops { + int (*read_prepare)(struct tmc_drvdata *drvdata); + int (*read_unprepare)(struct tmc_drvdata *drvdata); + ssize_t (*get_trace_data)(struct tmc_drvdata *drvdata, loff_t pos, + size_t len, char **bufpp); }; struct etr_buf_operations { From 7620b614b6a1da937b1b6cc9e11328de6ddd9981 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:54 +0800 Subject: [PATCH 0047/1058] FROMLIST: coresight: etr: add a new function to retrieve the CTCU device Add tmc_etr_get_ctcu_device function to find the ptr of the coresight_device of the CTCU device if the CTCU device is connected to the TMC ETR device. Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-4-8fbbf22e8381@oss.qualcomm.com/ Signed-off-by: Jie Gan --- .../hwtracing/coresight/coresight-tmc-etr.c | 24 +++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc.h | 1 + 2 files changed, 25 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 9b3ef73e9cf27..2b26ce6455a7b 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -865,6 +865,30 @@ tmc_etr_get_catu_device(struct tmc_drvdata *drvdata) } EXPORT_SYMBOL_GPL(tmc_etr_get_catu_device); +/* + * TMC ETR could be connected to a CTCU device, which can provide ATID filter + * and byte-cntr service. This is represented by the output port of the TMC + * (ETR) connected to the input port of the CTCU. + * + * Returns : coresight_device ptr for the CTCU device if a CTCU is found. + * : NULL otherwise. + */ +struct coresight_device * +tmc_etr_get_ctcu_device(struct tmc_drvdata *drvdata) +{ + struct coresight_device *etr = drvdata->csdev; + union coresight_dev_subtype ctcu_subtype = { + .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU + }; + + if (!IS_ENABLED(CONFIG_CORESIGHT_CTCU)) + return NULL; + + return coresight_find_output_type(etr->pdata, CORESIGHT_DEV_TYPE_HELPER, + ctcu_subtype); +} +EXPORT_SYMBOL_GPL(tmc_etr_get_ctcu_device); + static const struct etr_buf_operations *etr_buf_ops[] = { [ETR_MODE_FLAT] = &etr_flat_buf_ops, [ETR_MODE_ETR_SG] = &etr_sg_buf_ops, diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index a14645b04624a..fbb0150798725 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -470,6 +470,7 @@ static inline uint32_t find_crash_tracedata_crc(struct tmc_drvdata *drvdata, } struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata); +struct coresight_device *tmc_etr_get_ctcu_device(struct tmc_drvdata *drvdata); void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu); void tmc_etr_remove_catu_ops(void); From abe0f9f7ff99eef29d9171cb6903acfa330589f6 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:55 +0800 Subject: [PATCH 0048/1058] FROMLIST: dt-bindings: arm: add an interrupt property for Coresight CTCU Add an interrupt property to CTCU device. The interrupt will be triggered when the data size in the ETR buffer exceeds the threshold of the BYTECNTRVAL register. Programming a threshold in the BYTECNTRVAL register of CTCU device will enable the interrupt. Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-5-8fbbf22e8381@oss.qualcomm.com/ Acked-by: Krzysztof Kozlowski Reviewed-by: Mike Leach Signed-off-by: Jie Gan --- .../devicetree/bindings/arm/qcom,coresight-ctcu.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml index e002f87361ad3..2981001a7d7f7 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml @@ -44,6 +44,11 @@ properties: items: - const: apb + interrupts: + items: + - description: Interrupt for the ETR device connected to in-port0. + - description: Interrupt for the ETR device connected to in-port1. + label: description: Description of a coresight device. @@ -65,6 +70,8 @@ additionalProperties: false examples: - | + #include + ctcu@1001000 { compatible = "qcom,sa8775p-ctcu"; reg = <0x1001000 0x1000>; @@ -72,6 +79,9 @@ examples: clocks = <&aoss_qmp>; clock-names = "apb"; + interrupts = , + ; + in-ports { #address-cells = <1>; #size-cells = <0>; From 8684e30f9b34247d2336f33a7ecc1f8744a7726e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 25 Jun 2026 18:45:56 +0800 Subject: [PATCH 0049/1058] FROMLIST: coresight: ctcu: enable byte-cntr for TMC ETR devices The byte-cntr function provided by the CTCU device is used to transfer data from the ETR buffer to the userspace. An interrupt is triggered if the data size exceeds the threshold set in the BYTECNTRVAL register. The interrupt handler counts the number of triggered interruptions and the read function will read the data from the synced ETR buffer. Switching the sysfs_buf when current buffer is full or the timeout is triggered and resets rrp and rwp registers after switched the buffer. The synced buffer will become available for reading after the switch. Byte-cntr workflow: start -> ctcu_enable(ctcu_byte_cntr_start) -> tmc_enable_etr_sink -> tmc_read_prepare_etr(jump to tmc_read_prepare_byte_cntr) -> tmc_etr_get_sysfs_trace(jump to tmc_byte_cntr_get_data) -> tmc_disable_etr_sink -> ctcu_disable(ctcu_byte_cntr_stop) -> tmc_read_unprepare_etr(jump to tmc_read_unprepare_byte_cntr) -> finish Link: https://lore.kernel.org/all/20260625-enable-byte-cntr-for-ctcu-v19-6-8fbbf22e8381@oss.qualcomm.com/ Signed-off-by: Jie Gan --- .../testing/sysfs-bus-coresight-devices-ctcu | 9 + drivers/hwtracing/coresight/Makefile | 2 +- .../coresight/coresight-ctcu-byte-cntr.c | 327 ++++++++++++++++++ .../hwtracing/coresight/coresight-ctcu-core.c | 127 ++++++- drivers/hwtracing/coresight/coresight-ctcu.h | 79 ++++- .../hwtracing/coresight/coresight-tmc-core.c | 3 +- .../hwtracing/coresight/coresight-tmc-etr.c | 115 +++++- drivers/hwtracing/coresight/coresight-tmc.h | 9 + 8 files changed, 646 insertions(+), 25 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu create mode 100644 drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu new file mode 100644 index 0000000000000..beef0be219690 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu @@ -0,0 +1,9 @@ +What: /sys/bus/coresight/devices//irq_enabled[0:1] +Date: June 2026 +KernelVersion: 7.3 +Contact: Tingwei Zhang ; Jinlong Mao ; Jie Gan +Description: + (RW) Configure the flag to enable interrupt to count data during CTCU enablement. + An interrupt is generated when the data size exceeds the value set in the IRQ register. + 0 : disable + 1 : enable diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index ab16d06783a57..821a1b06b20c2 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -55,5 +55,5 @@ coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o -coresight-ctcu-y := coresight-ctcu-core.o +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c new file mode 100644 index 0000000000000..5ab97a71f02f6 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +#include "coresight-ctcu.h" +#include "coresight-priv.h" +#include "coresight-tmc.h" + +static irqreturn_t byte_cntr_handler(int irq, void *data) +{ + struct ctcu_byte_cntr *byte_cntr_data = data; + + atomic_inc(&byte_cntr_data->irq_cnt); + wake_up(&byte_cntr_data->wq); + + return IRQ_HANDLED; +} + +static void ctcu_cfg_byte_cntr_reg(struct ctcu_drvdata *drvdata, u32 val, + u32 offset) +{ + /* A one value for IRQCTRL register represents 8 bytes */ + ctcu_program_register(drvdata, val / 8, offset); +} + +static struct ctcu_byte_cntr *ctcu_get_byte_cntr(struct coresight_device *ctcu, + struct coresight_device *etr) +{ + struct ctcu_drvdata *drvdata = dev_get_drvdata(ctcu->dev.parent); + int port; + + port = coresight_get_in_port(etr, ctcu); + if (port < 0 || port > 1) + return NULL; + + return &drvdata->byte_cntr_data[port]; +} + +static bool ctcu_byte_cntr_switch_buffer(struct tmc_drvdata *etr_drvdata, + struct ctcu_byte_cntr *byte_cntr_data) +{ + struct etr_buf_node *nd, *next, *curr_node = NULL, *picked_node = NULL; + struct etr_buf *curr_buf = etr_drvdata->sysfs_buf; + bool found_free_buf = false; + unsigned long flags; + + if (WARN_ON(!etr_drvdata || !byte_cntr_data)) + return false; + + /* Stop the ETR before initiating the switch */ + if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED) + tmc_etr_enable_disable_hw(etr_drvdata, false); + + /* + * Serialise the sysfs_buf/etr_buf swap against the ETR sink + * enable/disable paths which also touch these fields under the + * spinlock. tmc_etr_enable_disable_hw() takes the same lock, so it + * must be called outside this critical section. + */ + raw_spin_lock_irqsave(&etr_drvdata->spinlock, flags); + list_for_each_entry_safe(nd, next, &etr_drvdata->etr_buf_list, link) { + /* curr_buf is free for next round */ + if (nd->sysfs_buf == curr_buf) { + nd->is_free = true; + curr_node = nd; + } else if (!found_free_buf && nd->is_free) { + picked_node = nd; + found_free_buf = true; + } + } + + if (found_free_buf) { + curr_node->pos = 0; + curr_node->reading = true; + byte_cntr_data->buf_node = curr_node; + etr_drvdata->sysfs_buf = picked_node->sysfs_buf; + etr_drvdata->etr_buf = picked_node->sysfs_buf; + picked_node->is_free = false; + /* Reset irq_cnt for next etr_buf */ + atomic_set(&byte_cntr_data->irq_cnt, 0); + } + raw_spin_unlock_irqrestore(&etr_drvdata->spinlock, flags); + + /* Restart the ETR once a free buffer is available */ + if (found_free_buf && + coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED) + tmc_etr_enable_disable_hw(etr_drvdata, true); + + return found_free_buf; +} + +/* + * ctcu_byte_cntr_get_data() - reads data from the deactivated and filled buffer. + * The byte-cntr reading work reads data from the deactivated and filled buffer. + * The read operation waits for a buffer to become available, either filled or + * upon timeout, and then reads trace data from the synced buffer. + */ +static ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *etr_drvdata, loff_t pos, + size_t len, char **bufpp) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct device *dev = &etr_drvdata->csdev->dev; + struct ctcu_byte_cntr *byte_cntr_data; + struct etr_buf *sysfs_buf; + atomic_t *irq_cnt; + ssize_t actual; + int ret; + + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled) + return -EINVAL; + + irq_cnt = &byte_cntr_data->irq_cnt; + +wait_buffer: + if (!byte_cntr_data->buf_node) { + ret = wait_event_interruptible_timeout(byte_cntr_data->wq, + (atomic_read(irq_cnt) >= MAX_IRQ_CNT - 1) || + !byte_cntr_data->enable, + BYTE_CNTR_TIMEOUT); + if (ret < 0) + return ret; + /* + * The current etr_buf is almost full or timeout is triggered, + * so switch the buffer and mark the switched buffer as reading. + */ + if (byte_cntr_data->enable) { + if (!ctcu_byte_cntr_switch_buffer(etr_drvdata, byte_cntr_data)) { + dev_err(dev, "Switch buffer failed for the byte-cntr\n"); + return -ENOMEM; + } + } else { + /* Exit byte-cntr reading */ + return 0; + } + } + + /* Check the status of current etr_buf */ + if (atomic_read(irq_cnt) >= MAX_IRQ_CNT) + dev_warn(dev, "Data overwrite happened\n"); + + pos = byte_cntr_data->buf_node->pos; + sysfs_buf = byte_cntr_data->buf_node->sysfs_buf; + actual = tmc_etr_read_sysfs_buf(sysfs_buf, pos, len, bufpp); + if (actual <= 0) { + /* Reset buf_node upon reading is finished or failed */ + byte_cntr_data->buf_node->reading = false; + byte_cntr_data->buf_node = NULL; + + /* + * Nothing in the buffer, waiting for the next buffer + * to be filled. + */ + if (actual == 0) + goto wait_buffer; + } + + return actual; +} + +static int tmc_read_prepare_byte_cntr(struct tmc_drvdata *etr_drvdata) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct ctcu_byte_cntr *byte_cntr_data; + unsigned long flags; + int ret = 0; + + /* byte-cntr is operating with SYSFS mode being enabled only */ + if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_SYSFS) + return -EINVAL; + + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled) + return -EINVAL; + + raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags); + if (byte_cntr_data->reading) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + return -EBUSY; + } + + /* byte_cntr_data->enable may race with ctcu_platform_remove() */ + if (!byte_cntr_data->enable) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + return -ENODEV; + } + + byte_cntr_data->reading = true; + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + /* Setup an available etr_buf_list for byte-cntr */ + ret = tmc_create_etr_buf_list(etr_drvdata, 2); + if (ret) { + byte_cntr_data->reading = false; + return ret; + } + + scoped_guard(raw_spinlock_irqsave, &byte_cntr_data->spin_lock) { + atomic_set(&byte_cntr_data->irq_cnt, 0); + /* + * Configure the byte-cntr register to enable IRQ. The + * configured size is 5% of the buffer_size. + */ + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, + etr_drvdata->size / MAX_IRQ_CNT, + byte_cntr_data->irq_ctrl_offset); + byte_cntr_data->buf_node = NULL; + } + /* enable_irq_wake() may sleep on slow-bus irqchips, call it unlocked */ + enable_irq_wake(byte_cntr_data->irq); + + return 0; +} + +static int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *etr_drvdata) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct ctcu_byte_cntr *byte_cntr_data; + + /* + * Do the unprepare operation only when the byte_cntr_data->reading + * is truly set + */ + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled || + !byte_cntr_data->reading) + return -EINVAL; + + tmc_clean_etr_buf_list(etr_drvdata); + scoped_guard(raw_spinlock_irqsave, &byte_cntr_data->spin_lock) { + /* Configure the byte-cntr register to disable IRQ */ + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, 0, + byte_cntr_data->irq_ctrl_offset); + byte_cntr_data->buf_node = NULL; + byte_cntr_data->reading = false; + } + /* + * The threshold IRQ is already disabled by the register write above, + * so no wake event can arrive here. disable_irq_wake() may sleep on + * slow-bus irqchips, so call it outside the spin_lock. + */ + disable_irq_wake(byte_cntr_data->irq); + wake_up(&byte_cntr_data->wq); + + return 0; +} + +const struct tmc_sysfs_ops byte_cntr_sysfs_ops = { + .read_prepare = tmc_read_prepare_byte_cntr, + .read_unprepare = tmc_read_unprepare_byte_cntr, + .get_trace_data = tmc_byte_cntr_get_data, +}; + +/* Start the byte-cntr function when the path is enabled. */ +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path) +{ + struct coresight_device *sink = coresight_get_sink(path); + struct ctcu_byte_cntr *byte_cntr_data; + + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink); + if (!byte_cntr_data) + return; + + /* Don't start byte-cntr function when irq_enabled is not set. */ + if (!byte_cntr_data->irq_enabled || byte_cntr_data->enable) + return; + + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock); + byte_cntr_data->enable = true; +} + +/* Stop the byte-cntr function when the path is disabled. */ +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path) +{ + struct coresight_device *sink = coresight_get_sink(path); + struct ctcu_byte_cntr *byte_cntr_data; + + if (coresight_get_mode(sink) == CS_MODE_SYSFS) + return; + + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink); + if (!byte_cntr_data) + return; + + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock); + byte_cntr_data->enable = false; +} + +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num) +{ + struct ctcu_byte_cntr *byte_cntr_data; + struct device_node *nd = dev->of_node; + int irq_num, ret, i, irq_registered = 0; + + for (i = 0; i < etr_num; i++) { + byte_cntr_data = &drvdata->byte_cntr_data[i]; + irq_num = of_irq_get(nd, i); + if (irq_num < 0) { + dev_err(dev, "Failed to get IRQ from DT for port%d\n", i); + continue; + } + + ret = devm_request_irq(dev, irq_num, byte_cntr_handler, + IRQF_TRIGGER_RISING | IRQF_SHARED, + dev_name(dev), byte_cntr_data); + if (ret) { + dev_err(dev, "Failed to register IRQ for port%d\n", i); + continue; + } + + byte_cntr_data->irq = irq_num; + byte_cntr_data->ctcu_drvdata = drvdata; + init_waitqueue_head(&byte_cntr_data->wq); + raw_spin_lock_init(&byte_cntr_data->spin_lock); + irq_registered++; + } + + if (irq_registered) + tmc_etr_set_byte_cntr_sysfs_ops(&byte_cntr_sysfs_ops); +} diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c index e8720026c9e3f..2da1a6f3d29f4 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -18,6 +19,7 @@ #include "coresight-ctcu.h" #include "coresight-priv.h" +#include "coresight-tmc.h" #define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset) #define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset) @@ -43,17 +45,21 @@ #define CTCU_ATID_REG_BIT(traceid) (traceid % 32) #define CTCU_ATID_REG_SIZE 0x10 +#define CTCU_ETR0_IRQCTRL 0x6c +#define CTCU_ETR1_IRQCTRL 0x70 #define CTCU_ETR0_ATID0 0xf8 #define CTCU_ETR1_ATID0 0x108 static const struct ctcu_etr_config sa8775p_etr_cfgs[] = { { - .atid_offset = CTCU_ETR0_ATID0, - .port_num = 0, + .atid_offset = CTCU_ETR0_ATID0, + .irq_ctrl_offset = CTCU_ETR0_IRQCTRL, + .port_num = 0, }, { - .atid_offset = CTCU_ETR1_ATID0, - .port_num = 1, + .atid_offset = CTCU_ETR1_ATID0, + .irq_ctrl_offset = CTCU_ETR1_IRQCTRL, + .port_num = 1, }, }; @@ -62,6 +68,85 @@ static const struct ctcu_config sa8775p_cfgs = { .num_etr_config = ARRAY_SIZE(sa8775p_etr_cfgs), }; +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset) +{ + CS_UNLOCK(drvdata->base); + ctcu_writel(drvdata, val, offset); + CS_LOCK(drvdata->base); +} + +static ssize_t irq_enabled_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + + if (!drvdata->byte_cntr_data[port].irq_ctrl_offset) + return -EINVAL; + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->byte_cntr_data[port].irq_enabled); +} + +static ssize_t irq_enabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + guard(raw_spinlock_irqsave)(&drvdata->byte_cntr_data[port].spin_lock); + if (drvdata->byte_cntr_data[port].reading) + return -EBUSY; + else if (drvdata->byte_cntr_data[port].irq_ctrl_offset) + drvdata->byte_cntr_data[port].irq_enabled = !!val; + + return size; +} + +static umode_t irq_enabled_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device_attribute *dev_attr = + container_of(attr, struct device_attribute, attr); + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(dev_attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct device *dev = kobj_to_dev(kobj); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + + if (drvdata && drvdata->byte_cntr_data[port].irq_ctrl_offset) + return attr->mode; + + return 0; +} + +static struct attribute *ctcu_attrs[] = { + ctcu_byte_cntr_irq_rw(0), + ctcu_byte_cntr_irq_rw(1), + NULL, +}; + +static struct attribute_group ctcu_attr_grp = { + .attrs = ctcu_attrs, + .is_visible = irq_enabled_is_visible, +}; + +static const struct attribute_group *ctcu_attr_grps[] = { + &ctcu_attr_grp, + NULL, +}; + static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset, u8 bit, bool enable) { @@ -140,11 +225,15 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, struct coresight_path *path) { + ctcu_byte_cntr_start(csdev, path); + return ctcu_set_etr_traceid(csdev, path, true); } static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path) { + ctcu_byte_cntr_stop(csdev, path); + return ctcu_set_etr_traceid(csdev, path, false); } @@ -195,7 +284,10 @@ static int ctcu_probe(struct platform_device *pdev) for (i = 0; i < cfgs->num_etr_config; i++) { etr_cfg = &cfgs->etr_cfgs[i]; drvdata->atid_offset[i] = etr_cfg->atid_offset; + drvdata->byte_cntr_data[i].irq_ctrl_offset = + etr_cfg->irq_ctrl_offset; } + ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config); } } @@ -209,6 +301,7 @@ static int ctcu_probe(struct platform_device *pdev) desc.dev = dev; desc.ops = &ctcu_ops; desc.access = CSDEV_ACCESS_IOMEM(base); + desc.groups = ctcu_attr_grps; raw_spin_lock_init(&drvdata->spin_lock); drvdata->csdev = coresight_register(&desc); @@ -244,10 +337,34 @@ static int ctcu_platform_probe(struct platform_device *pdev) static void ctcu_platform_remove(struct platform_device *pdev) { struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev); + struct ctcu_byte_cntr *byte_cntr_data; + unsigned long flags; + int i; if (WARN_ON(!drvdata)) return; + /* + * Signal all active byte-cntr readers to exit, then wait for them to + * finish before resetting the ops pointer and freeing driver data. + * Without this, a reader blocked in wait_event_interruptible_timeout() + * would access the freed ctcu_drvdata wait-queue head (use-after-free). + */ + for (i = 0; i < ETR_MAX_NUM; i++) { + byte_cntr_data = &drvdata->byte_cntr_data[i]; + raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags); + /* Set enable=false for all ports to signal teardown to racing readers */ + byte_cntr_data->enable = false; + if (!byte_cntr_data->reading) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + continue; + } + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + wake_up_all(&byte_cntr_data->wq); + wait_event(byte_cntr_data->wq, !byte_cntr_data->reading); + } + + tmc_etr_reset_byte_cntr_sysfs_ops(); ctcu_remove(pdev); pm_runtime_disable(&pdev->dev); } diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h index e9594c38dd91c..a2ae0a0d91d0f 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu.h +++ b/drivers/hwtracing/coresight/coresight-ctcu.h @@ -1,23 +1,31 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef _CORESIGHT_CTCU_H #define _CORESIGHT_CTCU_H + +#include #include "coresight-trace-id.h" /* Maximum number of supported ETR devices for a single CTCU. */ #define ETR_MAX_NUM 2 +#define BYTE_CNTR_TIMEOUT (3 * HZ) +#define MAX_IRQ_CNT 20 + /** * struct ctcu_etr_config * @atid_offset: offset to the ATID0 Register. - * @port_num: in-port number of CTCU device that connected to ETR. + * @port_num: in-port number of the CTCU device that connected to ETR. + * @irq_ctrl_offset: offset to the BYTECNTRVAL register. */ struct ctcu_etr_config { const u32 atid_offset; const u32 port_num; + const u32 irq_ctrl_offset; }; struct ctcu_config { @@ -25,15 +33,68 @@ struct ctcu_config { int num_etr_config; }; -struct ctcu_drvdata { - void __iomem *base; - struct clk *apb_clk; - struct device *dev; - struct coresight_device *csdev; +/** + * struct ctcu_byte_cntr + * @enable: indicates that byte_cntr function is enabled or not. + * @irq_enabled: indicates that the interruption is enabled. + * @reading: indicates that byte_cntr is reading. + * @irq: allocated number of the IRQ. + * @irq_cnt: IRQ count number of the triggered interruptions. + * @wq: waitqueue for reading data from ETR buffer. + * @spin_lock: spinlock of the byte_cntr_data. + * @irq_ctrl_offset: offset to the BYTECNTVAL Register. + * @ctcu_drvdata: drvdata of the CTCU device. + * @buf_node: etr_buf_node for reading. + */ +struct ctcu_byte_cntr { + bool enable; + bool irq_enabled; + bool reading; + int irq; + atomic_t irq_cnt; + wait_queue_head_t wq; raw_spinlock_t spin_lock; - u32 atid_offset[ETR_MAX_NUM]; + u32 irq_ctrl_offset; + struct ctcu_drvdata *ctcu_drvdata; + struct etr_buf_node *buf_node; +}; + +struct ctcu_drvdata { + void __iomem *base; + struct clk *apb_clk; + struct device *dev; + struct coresight_device *csdev; + struct ctcu_byte_cntr byte_cntr_data[ETR_MAX_NUM]; + raw_spinlock_t spin_lock; + u32 atid_offset[ETR_MAX_NUM]; /* refcnt for each traceid of each sink */ - u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP]; + u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP]; }; +/** + * struct ctcu_byte_cntr_irq_attribute + * @attr: The device attribute. + * @port: port number. + */ +struct ctcu_byte_cntr_irq_attribute { + struct device_attribute attr; + u8 port; +}; + +#define ctcu_byte_cntr_irq_rw(port) \ + (&((struct ctcu_byte_cntr_irq_attribute[]) { \ + { \ + __ATTR(irq_enabled##port, 0644, irq_enabled_show, \ + irq_enabled_store), \ + port, \ + } \ + })[0].attr.attr) + +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset); + +/* Byte-cntr functions */ +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path); +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path); +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num); + #endif diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 4b40b692be4d8..6ad09995ba87c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -293,7 +293,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, return -EFAULT; } - *ppos += actual; + if (!tmc_etr_update_buf_node_pos(drvdata, actual)) + *ppos += actual; dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual); return actual; diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 2b26ce6455a7b..e78f8891f11e0 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1168,6 +1168,9 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, return rc; } +/* Assumes a single CTCU instance per system, as on all current Qualcomm SoCs. */ +static const struct tmc_sysfs_ops *byte_cntr_sysfs_ops; + /* * Return the available trace data in the buffer (starts at etr_buf->offset, * limited by etr_buf->len) from @pos, with a maximum limit of @len, @@ -1178,23 +1181,39 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, * We are protected here by drvdata->reading != 0, which ensures the * sysfs_buf stays alive. */ -ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, - loff_t pos, size_t len, char **bufpp) +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos, + size_t len, char **bufpp) { s64 offset; ssize_t actual = len; - struct etr_buf *etr_buf = drvdata->sysfs_buf; - if (pos + actual > etr_buf->len) - actual = etr_buf->len - pos; + if (pos + actual > sysfs_buf->len) + actual = sysfs_buf->len - pos; if (actual <= 0) return actual; /* Compute the offset from which we read the data */ - offset = etr_buf->offset + pos; - if (offset >= etr_buf->size) - offset -= etr_buf->size; - return tmc_etr_buf_get_data(etr_buf, offset, actual, bufpp); + offset = sysfs_buf->offset + pos; + if (offset >= sysfs_buf->size) + offset -= sysfs_buf->size; + return tmc_etr_buf_get_data(sysfs_buf, offset, actual, bufpp); +} +EXPORT_SYMBOL_GPL(tmc_etr_read_sysfs_buf); + +ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, + loff_t pos, size_t len, char **bufpp) +{ + ssize_t ret; + const struct tmc_sysfs_ops *byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + + if (byte_cntr_ops) { + ret = byte_cntr_ops->get_trace_data(drvdata, pos, len, bufpp); + /* Return the filled buffer */ + if (ret > 0 || ret == -ENOMEM) + return ret; + } + + return tmc_etr_read_sysfs_buf(drvdata->sysfs_buf, pos, len, bufpp); } static struct etr_buf * @@ -1248,6 +1267,39 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) } +static void tmc_etr_reset_sysfs_buf(struct tmc_drvdata *drvdata) +{ + u32 sts; + + CS_UNLOCK(drvdata->base); + tmc_write_rrp(drvdata, drvdata->sysfs_buf->hwaddr); + tmc_write_rwp(drvdata, drvdata->sysfs_buf->hwaddr); + sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL; + writel_relaxed(sts, drvdata->base + TMC_STS); + CS_LOCK(drvdata->base); +} + +/** + * tmc_etr_enable_disable_hw - enable/disable the ETR hw. + * @drvdata: drvdata of the TMC device. + * @enable: indicates enable/disable. + */ +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (enable) { + tmc_etr_reset_sysfs_buf(drvdata); + __tmc_etr_enable_hw(drvdata); + } else { + __tmc_etr_disable_hw(drvdata); + } + + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); +} +EXPORT_SYMBOL_GPL(tmc_etr_enable_disable_hw); + void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { __tmc_etr_disable_hw(drvdata); @@ -2068,15 +2120,54 @@ int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes) } EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list); +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops) +{ + WRITE_ONCE(byte_cntr_sysfs_ops, sysfs_ops); +} +EXPORT_SYMBOL_GPL(tmc_etr_set_byte_cntr_sysfs_ops); + +void tmc_etr_reset_byte_cntr_sysfs_ops(void) +{ + WRITE_ONCE(byte_cntr_sysfs_ops, NULL); +} +EXPORT_SYMBOL_GPL(tmc_etr_reset_byte_cntr_sysfs_ops); + +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size) +{ + struct etr_buf_node *nd, *next; + + if (drvdata->config_type != TMC_CONFIG_TYPE_ETR) + return false; + + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) { + if (nd && nd->reading) { + nd->pos += size; + return true; + } + } + + return false; +} + int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret = 0; unsigned long flags; + const struct tmc_sysfs_ops *byte_cntr_ops; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; + byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + if (byte_cntr_ops) { + ret = byte_cntr_ops->read_prepare(drvdata); + if (!ret || ret == -EBUSY) + return ret; + + ret = 0; + } + raw_spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { ret = -EBUSY; @@ -2108,11 +2199,17 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) { unsigned long flags; struct etr_buf *sysfs_buf = NULL; + const struct tmc_sysfs_ops *byte_cntr_ops; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; + byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + if (byte_cntr_ops) + if (!byte_cntr_ops->read_unprepare(drvdata)) + return 0; + raw_spin_lock_irqsave(&drvdata->spinlock, flags); /* RE-enable the TMC if need be */ diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index fbb0150798725..a15e2f93f16a5 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -211,12 +211,15 @@ struct tmc_resrv_buf { /** * @sysfs_buf: Allocated sysfs_buf. * @is_free: Indicates whether the buffer is free to choose. + * @reading: Indicates byte_cntr is reading the buffer attached to + * the node. * @pos: Offset to the start of the buffer. * @link: list_head of the node. */ struct etr_buf_node { struct etr_buf *sysfs_buf; bool is_free; + bool reading; loff_t pos; struct list_head link; }; @@ -480,5 +483,11 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, extern const struct attribute_group coresight_etr_group; void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata); int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes); +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops); +void tmc_etr_reset_byte_cntr_sysfs_ops(void); +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable); +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size); +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos, + size_t len, char **bufpp); #endif From 79ef0efaeef1d3e7a4d8be2fe199cd161e028314 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:30 -0700 Subject: [PATCH 0050/1058] FROMLIST: dt-bindings: arm: Add support for Qualcomm TGU trace The Trigger Generation Unit (TGU) is designed to detect patterns or sequences within a specific region of the System on Chip (SoC). Once configured and activated, it monitors sense inputs and can detect a pre-programmed state or sequence across clock cycles, subsequently producing a trigger. TGU configuration space offset table x-------------------------x | | | | | | Step configuration | | space layout | coresight management | x-------------x | registers | |---> | | | | | | reserve | | | | | | |-------------------------| | |-------------| | | | | priority[3] | | step[7] |<-- | |-------------| |-------------------------| | | | priority[2] | | | | | |-------------| | ... | |Steps region | | priority[1] | | | | | |-------------| |-------------------------| | | | priority[0] | | |<-- | |-------------| | step[0] |--------------------> | | |-------------------------| | condition | | | | | | control and status | x-------------x | space | | | x-------------------------x |Timer/Counter| | | x-------------x TGU Configuration in Hardware The TGU provides a step region for user configuration, similar to a flow chart. Each step region consists of three register clusters: 1.Priority Region: Sets the required signals with priority. 2.Condition Region: Defines specific requirements (e.g., signal A reaches three times) and the subsequent action once the requirement is met. 3.Timer/Counter (Optional): Provides timing or counting functionality. Add a new tgu.yaml file to describe the bindings required to define the TGU in the device trees. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-2-songwei.chai@oss.qualcomm.com/ Reviewed-by: Rob Herring (Arm) Signed-off-by: Songwei Chai --- .../devicetree/bindings/arm/qcom,tgu.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/qcom,tgu.yaml diff --git a/Documentation/devicetree/bindings/arm/qcom,tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml new file mode 100644 index 0000000000000..76440f2497b97 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +# Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/qcom,tgu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Trigger Generation Unit - TGU + +description: | + The Trigger Generation Unit (TGU) is a Data Engine which can be utilized + to sense a plurality of signals and create a trigger into the CTI or + generate interrupts to processors. The TGU is like the trigger circuit + of a Logic Analyzer. The corresponding trigger logic can be realized by + configuring the conditions for each step after sensing the signal. + Once setup and enabled, it will observe sense inputs and based upon + the activity of those inputs, even over clock cycles, may detect a + preprogrammed state/sequence and then produce a trigger or interrupt. + + The primary use case of the TGU is to detect patterns or sequences on a + given set of signals within some region to identify the issue in time + once there is abnormal behavior in the subsystem. + +maintainers: + - Mao Jinlong + - Songwei Chai + +# Need a custom select here or 'arm,primecell' will match on lots of nodes +select: + properties: + compatible: + contains: + enum: + - qcom,tgu + required: + - compatible + +properties: + compatible: + items: + - const: qcom,tgu + - const: arm,primecell + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: apb_pclk + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x10b0e000 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +... From fdbd044220082e13dfc8979b0c006c27286c8892 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:31 -0700 Subject: [PATCH 0051/1058] FROMLIST: qcom-tgu: Add TGU driver Add driver to support device TGU (Trigger Generation Unit). TGU is a Data Engine which can be utilized to sense a plurality of signals and create a trigger into the CTI or generate interrupts to processors. Add probe/enable/disable functions for tgu. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-3-songwei.chai@oss.qualcomm.com/ Signed-off-by: Songwei Chai Acked-by: Konrad Dybcio --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 9 + drivers/Makefile | 1 + drivers/hwtracing/Kconfig | 2 + drivers/hwtracing/qcom/Kconfig | 20 ++ drivers/hwtracing/qcom/Makefile | 3 + drivers/hwtracing/qcom/tgu.c | 193 ++++++++++++++++++ drivers/hwtracing/qcom/tgu.h | 51 +++++ 7 files changed, 279 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-amba-devices-tgu create mode 100644 drivers/hwtracing/qcom/Kconfig create mode 100644 drivers/hwtracing/qcom/Makefile create mode 100644 drivers/hwtracing/qcom/tgu.c create mode 100644 drivers/hwtracing/qcom/tgu.h diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu new file mode 100644 index 0000000000000..f877a00fcaa58 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -0,0 +1,9 @@ +What: /sys/bus/amba/devices//enable_tgu +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the enable/disable status of TGU + Accepts only one of the 2 values - 0 or 1. + 0 : disable TGU. + 1 : enable TGU. diff --git a/drivers/Makefile b/drivers/Makefile index 0841ea851847e..6a2cbe5b340f5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -176,6 +176,7 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_USB4) += thunderbolt/ obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ obj-y += hwtracing/intel_th/ +obj-y += hwtracing/qcom/ obj-$(CONFIG_STM) += hwtracing/stm/ obj-$(CONFIG_HISI_PTT) += hwtracing/ptt/ obj-y += android/ diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig index 911ee977103c0..8a640218eed84 100644 --- a/drivers/hwtracing/Kconfig +++ b/drivers/hwtracing/Kconfig @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig" source "drivers/hwtracing/ptt/Kconfig" +source "drivers/hwtracing/qcom/Kconfig" + endmenu diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig new file mode 100644 index 0000000000000..5c94c75ffa396 --- /dev/null +++ b/drivers/hwtracing/qcom/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# QCOM specific hwtracing drivers +# +menu "Qualcomm specific hwtracing drivers" + +config QCOM_TGU + tristate "QCOM Trigger Generation Unit driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on ARM_AMBA + help + This driver provides support for Trigger Generation Unit that is + used to detect patterns or sequences on a given set of signals. + TGU is used to monitor a particular bus within a given region to + detect illegal transaction sequences or slave responses. It is also + used to monitor a data stream to detect protocol violations and to + provide a trigger point for centering data around a specific event + within the trace data buffer. + +endmenu diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile new file mode 100644 index 0000000000000..5a0a868c1ea0d --- /dev/null +++ b/drivers/hwtracing/qcom/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_QCOM_TGU) += tgu.o diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c new file mode 100644 index 0000000000000..49c8f710b9318 --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tgu.h" + +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +{ + TGU_UNLOCK(drvdata->base); + /* Enable TGU to program the triggers */ + writel(1, drvdata->base + TGU_CONTROL); + TGU_LOCK(drvdata->base); +} + +static int tgu_enable(struct device *dev) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + + guard(spinlock)(&drvdata->lock); + drvdata->enabled = true; + + tgu_write_all_hw_regs(drvdata); + + return 0; +} + +static void tgu_do_disable(struct tgu_drvdata *drvdata) +{ + TGU_UNLOCK(drvdata->base); + writel(0, drvdata->base + TGU_CONTROL); + TGU_LOCK(drvdata->base); + + drvdata->enabled = false; +} + +static void tgu_disable(struct device *dev) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + + guard(spinlock)(&drvdata->lock); + if (!drvdata->enabled) + return; + + tgu_do_disable(drvdata); +} + +static ssize_t enable_tgu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + bool enabled; + + guard(spinlock)(&drvdata->lock); + enabled = drvdata->enabled; + + return sysfs_emit(buf, "%d\n", !!enabled); +} + +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */ +static ssize_t enable_tgu_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret || val > 1) + return -EINVAL; + + if (val) { + scoped_guard(spinlock, &drvdata->lock) { + if (drvdata->enabled) + return -EBUSY; + } + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret = tgu_enable(dev); + if (ret) { + pm_runtime_put(dev); + return ret; + } + } else { + scoped_guard(spinlock, &drvdata->lock) { + if (!drvdata->enabled) + return -EINVAL; + } + + tgu_disable(dev); + pm_runtime_put(dev); + } + + return size; +} +static DEVICE_ATTR_RW(enable_tgu); + +static struct attribute *tgu_common_attrs[] = { + &dev_attr_enable_tgu.attr, + NULL, +}; + +static const struct attribute_group tgu_common_grp = { + .attrs = tgu_common_attrs, + NULL, +}; + +static const struct attribute_group *tgu_attr_groups[] = { + &tgu_common_grp, + NULL, +}; + +static int tgu_probe(struct amba_device *adev, const struct amba_id *id) +{ + struct device *dev = &adev->dev; + struct tgu_drvdata *drvdata; + int ret; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &adev->dev; + dev_set_drvdata(dev, drvdata); + + drvdata->base = devm_ioremap_resource(dev, &adev->res); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + spin_lock_init(&drvdata->lock); + + ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); + if (ret) { + dev_err(dev, "failed to create sysfs groups: %d\n", ret); + return ret; + } + + drvdata->enabled = false; + + pm_runtime_put(&adev->dev); + + return 0; +} + +static void tgu_remove(struct amba_device *adev) +{ + struct device *dev = &adev->dev; + + sysfs_remove_groups(&dev->kobj, tgu_attr_groups); + + tgu_disable(dev); +} + +static const struct amba_id tgu_ids[] = { + { + .id = 0x000f0e00, + .mask = 0x000fffff, + }, + { 0, 0, NULL }, +}; + +MODULE_DEVICE_TABLE(amba, tgu_ids); + +static struct amba_driver tgu_driver = { + .drv = { + .name = "qcom-tgu", + .suppress_bind_attrs = true, + }, + .probe = tgu_probe, + .remove = tgu_remove, + .id_table = tgu_ids, +}; + +module_amba_driver(tgu_driver); + +MODULE_AUTHOR("Songwei Chai "); +MODULE_AUTHOR("Jinlong Mao "); +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h new file mode 100644 index 0000000000000..dd7533b9d7350 --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_TGU_H +#define _QCOM_TGU_H + +/* Register addresses */ +#define TGU_CONTROL 0x0000 +#define TGU_LAR 0xfb0 +#define TGU_UNLOCK_OFFSET 0xc5acce55 + +static inline void TGU_LOCK(void __iomem *addr) +{ + do { + /* Wait for things to settle */ + mb(); + writel_relaxed(0x0, addr + TGU_LAR); + } while (0); +} + +static inline void TGU_UNLOCK(void __iomem *addr) +{ + do { + writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR); + /* Make sure everyone has seen this */ + mb(); + } while (0); +} + +/** + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) + * @base: Memory-mapped base address of the TGU device + * @dev: Pointer to the associated device structure + * @lock: Spinlock for handling concurrent access to private data + * @enabled: Flag indicating whether the TGU device is enabled + * + * This structure defines the data associated with a TGU device, + * including its base address, device pointers, clock, spinlock for + * synchronization, trigger data pointers, maximum limits for various + * trigger-related parameters, and enable status. + */ +struct tgu_drvdata { + void __iomem *base; + struct device *dev; + spinlock_t lock; + bool enabled; +}; + +#endif From 9d7592edecf04f154346b8c2bf14955d55a0c44d Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:32 -0700 Subject: [PATCH 0052/1058] FROMLIST: qcom-tgu: Add signal priority support Like circuit of a Logic analyzer, in TGU, the requirement could be configured in each step and the trigger will be created once the requirements are met. Add priority functionality here to sort the signals into different priorities. The signal which is wanted could be configured in each step's priority node, the larger number means the higher priority and the signal with higher priority will be sensed more preferentially. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-4-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 + drivers/hwtracing/qcom/tgu.c | 161 ++++++++++++++++++ drivers/hwtracing/qcom/tgu.h | 114 +++++++++++++ 3 files changed, 282 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index f877a00fcaa58..223873789ca61 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -7,3 +7,10 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : disable TGU. 1 : enable TGU. + +What: /sys/bus/amba/devices//step[0:7]_priority[0:3]/reg[0:17] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the sensed signal with specific step and priority for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 49c8f710b9318..7d69986c3e3d2 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -14,14 +14,123 @@ #include "tgu.h" +static int calculate_array_location(struct tgu_drvdata *drvdata, + int step_index, int operation_index, + int reg_index) +{ + return operation_index * (drvdata->num_step) * (drvdata->num_reg) + + step_index * (drvdata->num_reg) + reg_index; +} + +static ssize_t tgu_dataset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + int index; + + index = calculate_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num); + + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[index]); +} + +static ssize_t tgu_dataset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + unsigned long val; + int index; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + guard(spinlock)(&tgu_drvdata->lock); + index = calculate_array_location(tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num); + + tgu_drvdata->value_table->priority[index] = val; + + return size; +} + +static umode_t tgu_node_visible(struct kobject *kobject, + struct attribute *attr, + int n) +{ + struct device *dev = kobj_to_dev(kobject); + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct device_attribute *dev_attr = + container_of(attr, struct device_attribute, attr); + struct tgu_attribute *tgu_attr = + container_of(dev_attr, struct tgu_attribute, attr); + + if (tgu_attr->step_index >= drvdata->num_step) + return SYSFS_GROUP_INVISIBLE; + + if (tgu_attr->reg_num >= drvdata->num_reg) + return 0; + + return attr->mode; +} + static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) { + int i, j, k, index; + TGU_UNLOCK(drvdata->base); + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < MAX_PRIORITY; j++) { + for (k = 0; k < drvdata->num_reg; k++) { + index = calculate_array_location( + drvdata, i, j, k); + + writel(drvdata->value_table->priority[index], + drvdata->base + + PRIORITY_REG_STEP(i, j, k)); + } + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); TGU_LOCK(drvdata->base); } +static void tgu_set_reg_number(struct tgu_drvdata *drvdata) +{ + int num_sense_input; + int num_reg; + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + num_sense_input = TGU_DEVID_SENSE_INPUT(devid); + num_reg = (num_sense_input * TGU_BITS_PER_SIGNAL) / LENGTH_REGISTER; + + if ((num_sense_input * TGU_BITS_PER_SIGNAL) % LENGTH_REGISTER) + num_reg++; + + drvdata->num_reg = num_reg; +} + +static void tgu_set_steps(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + drvdata->num_step = TGU_DEVID_STEPS(devid); +} + static int tgu_enable(struct device *dev) { struct tgu_drvdata *drvdata = dev_get_drvdata(dev); @@ -121,6 +230,38 @@ static const struct attribute_group tgu_common_grp = { static const struct attribute_group *tgu_attr_groups[] = { &tgu_common_grp, + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3), NULL, }; @@ -128,6 +269,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; + unsigned int *priority; + size_t priority_size; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -143,12 +286,30 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) spin_lock_init(&drvdata->lock); + tgu_set_reg_number(drvdata); + tgu_set_steps(drvdata); + ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); if (ret) { dev_err(dev, "failed to create sysfs groups: %d\n", ret); return ret; } + drvdata->value_table = + devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL); + if (!drvdata->value_table) + return -ENOMEM; + + priority_size = MAX_PRIORITY * drvdata->num_reg * drvdata->num_step; + + priority = devm_kcalloc(dev, priority_size, + sizeof(*drvdata->value_table->priority), + GFP_KERNEL); + if (!priority) + return -ENOMEM; + + drvdata->value_table->priority = priority; + drvdata->enabled = false; pm_runtime_put(&adev->dev); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index dd7533b9d7350..f994d83acb1d6 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -10,6 +10,114 @@ #define TGU_CONTROL 0x0000 #define TGU_LAR 0xfb0 #define TGU_UNLOCK_OFFSET 0xc5acce55 +#define TGU_DEVID 0xfc8 + +#define TGU_DEVID_SENSE_INPUT(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 10), devid_val)) +#define TGU_DEVID_STEPS(devid_val) \ + ((int)FIELD_GET(GENMASK(6, 3), devid_val)) +#define TGU_BITS_PER_SIGNAL 4 +#define LENGTH_REGISTER 32 + +/* + * TGU configuration space Step configuration + * offset table space layout + * x-------------------------x$ x-------------x$ + * | |$ | |$ + * | | | reserve |$ + * | | | |$ + * |coresight management | |-------------|base+n*0x1D8+0x1F4$ + * | registers | |---> |priority[3] |$ + * | | | |-------------|base+n*0x1D8+0x194$ + * | | | |priority[2] |$ + * |-------------------------| | |-------------|base+n*0x1D8+0x134$ + * | | | |priority[1] |$ + * | step[7] | | |-------------|base+n*0x1D8+0xD4$ + * |-------------------------|->base+0x40+7*0x1D8 | |priority[0] |$ + * | | | |-------------|base+n*0x1D8+0x74$ + * | ... | | | condition |$ + * | | | | select |$ + * |-------------------------|->base+0x40+1*0x1D8 | |-------------|base+n*0x1D8+0x60$ + * | | | | condition |$ + * | step[0] |--------------------> | decode |$ + * |-------------------------|-> base+0x40 |-------------|base+n*0x1D8+0x50$ + * | | | |$ + * | Control and status space| |Timer/Counter|$ + * | space | | |$ + * x-------------------------x->base x-------------x base+n*0x1D8+0x40$ + * + */ +#define STEP_OFFSET 0x1D8 +#define PRIORITY_START_OFFSET 0x0074 +#define PRIORITY_OFFSET 0x60 +#define REG_OFFSET 0x4 + +/* Calculate compare step addresses */ +#define PRIORITY_REG_STEP(step, priority, reg)\ + (PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\ + REG_OFFSET * reg + STEP_OFFSET * step) + +#define tgu_dataset_rw(name, step_index, type, reg_num) \ + (&((struct tgu_attribute[]){ { \ + __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ + step_index, \ + type, \ + reg_num, \ + } })[0].attr.attr) + +#define STEP_PRIORITY(step_index, reg_num, priority) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \ + reg_num) + +#define STEP_PRIORITY_LIST(step_index, priority) \ + {STEP_PRIORITY(step_index, 0, priority), \ + STEP_PRIORITY(step_index, 1, priority), \ + STEP_PRIORITY(step_index, 2, priority), \ + STEP_PRIORITY(step_index, 3, priority), \ + STEP_PRIORITY(step_index, 4, priority), \ + STEP_PRIORITY(step_index, 5, priority), \ + STEP_PRIORITY(step_index, 6, priority), \ + STEP_PRIORITY(step_index, 7, priority), \ + STEP_PRIORITY(step_index, 8, priority), \ + STEP_PRIORITY(step_index, 9, priority), \ + STEP_PRIORITY(step_index, 10, priority), \ + STEP_PRIORITY(step_index, 11, priority), \ + STEP_PRIORITY(step_index, 12, priority), \ + STEP_PRIORITY(step_index, 13, priority), \ + STEP_PRIORITY(step_index, 14, priority), \ + STEP_PRIORITY(step_index, 15, priority), \ + STEP_PRIORITY(step_index, 16, priority), \ + STEP_PRIORITY(step_index, 17, priority), \ + NULL \ + } + +#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_priority" #priority \ + }) + +enum operation_index { + TGU_PRIORITY0, + TGU_PRIORITY1, + TGU_PRIORITY2, + TGU_PRIORITY3, +}; + +/* Maximum priority that TGU supports */ +#define MAX_PRIORITY 4 + +struct tgu_attribute { + struct device_attribute attr; + u32 step_index; + enum operation_index operation_index; + u32 reg_num; +}; + +struct value_table { + unsigned int *priority; +}; static inline void TGU_LOCK(void __iomem *addr) { @@ -35,6 +143,9 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @dev: Pointer to the associated device structure * @lock: Spinlock for handling concurrent access to private data * @enabled: Flag indicating whether the TGU device is enabled + * @value_table: Store given value based on relevant parameters + * @num_reg: Maximum number of registers + * @num_step: Maximum step size * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -46,6 +157,9 @@ struct tgu_drvdata { struct device *dev; spinlock_t lock; bool enabled; + struct value_table *value_table; + int num_reg; + int num_step; }; #endif From ca3acff9326dbd87bb3af07b68a5f6f1f7d3d4eb Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:33 -0700 Subject: [PATCH 0053/1058] FROMLIST: qcom-tgu: Add TGU decode support Decoding is when all the potential pieces for creating a trigger are brought together for a given step. Example - there may be a counter keeping track of some occurrences and a priority-group that is being used to detect a pattern on the sense inputs. These 2 inputs to condition_decode must be programmed, for a given step, to establish the condition for the trigger, or movement to another steps. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-5-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 + drivers/hwtracing/qcom/tgu.c | 157 +++++++++++++++--- drivers/hwtracing/qcom/tgu.h | 27 +++ 3 files changed, 170 insertions(+), 21 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 223873789ca61..4ef0d696d3d0e 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -14,3 +14,10 @@ KernelVersion: 7.1 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the sensed signal with specific step and priority for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_decode/reg[0:3] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the decode mode with specific step for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 7d69986c3e3d2..937211923d937 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -18,8 +18,33 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, int step_index, int operation_index, int reg_index) { - return operation_index * (drvdata->num_step) * (drvdata->num_reg) + - step_index * (drvdata->num_reg) + reg_index; + switch (operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return operation_index * (drvdata->num_step) * + (drvdata->num_reg) + + step_index * (drvdata->num_reg) + reg_index; + case TGU_CONDITION_DECODE: + return step_index * (drvdata->num_condition_decode) + + reg_index; + default: + break; + } + + return -EINVAL; +} + +static int check_array_location(struct tgu_drvdata *drvdata, int step, + int ops, int reg) +{ + int result = calculate_array_location(drvdata, step, ops, reg); + + if (result == -EINVAL) + dev_err(drvdata->dev, "check array location - Fail\n"); + + return result; } static ssize_t tgu_dataset_show(struct device *dev, @@ -30,12 +55,26 @@ static ssize_t tgu_dataset_show(struct device *dev, container_of(attr, struct tgu_attribute, attr); int index; - index = calculate_array_location(drvdata, tgu_attr->step_index, - tgu_attr->operation_index, - tgu_attr->reg_num); - - return sysfs_emit(buf, "0x%x\n", - drvdata->value_table->priority[index]); + index = check_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, tgu_attr->reg_num); + + if (index == -EINVAL) + return index; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[index]); + case TGU_CONDITION_DECODE: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_decode[index]); + default: + break; + } + return -EINVAL; } static ssize_t tgu_dataset_store(struct device *dev, @@ -54,13 +93,31 @@ static ssize_t tgu_dataset_store(struct device *dev, return ret; guard(spinlock)(&tgu_drvdata->lock); - index = calculate_array_location(tgu_drvdata, tgu_attr->step_index, + index = check_array_location(tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index, tgu_attr->reg_num); - tgu_drvdata->value_table->priority[index] = val; + if (index == -EINVAL) + return index; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + tgu_drvdata->value_table->priority[index] = val; + ret = size; + break; + case TGU_CONDITION_DECODE: + tgu_drvdata->value_table->condition_decode[index] = val; + ret = size; + break; + default: + ret = -EINVAL; + break; + } - return size; + return ret; } static umode_t tgu_node_visible(struct kobject *kobject, @@ -77,13 +134,26 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->step_index >= drvdata->num_step) return SYSFS_GROUP_INVISIBLE; - if (tgu_attr->reg_num >= drvdata->num_reg) - return 0; + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + if (tgu_attr->reg_num < drvdata->num_reg) + return attr->mode; + break; + case TGU_CONDITION_DECODE: + if (tgu_attr->reg_num < drvdata->num_condition_decode) + return attr->mode; + break; + default: + break; + } - return attr->mode; + return 0; } -static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) { int i, j, k, index; @@ -91,8 +161,10 @@ static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) for (i = 0; i < drvdata->num_step; i++) { for (j = 0; j < MAX_PRIORITY; j++) { for (k = 0; k < drvdata->num_reg; k++) { - index = calculate_array_location( + index = check_array_location( drvdata, i, j, k); + if (index == -EINVAL) + goto exit; writel(drvdata->value_table->priority[index], drvdata->base + @@ -100,9 +172,23 @@ static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) } } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_decode; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_DECODE, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_decode[index], + drvdata->base + CONDITION_DECODE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); +exit: TGU_LOCK(drvdata->base); + return index >= 0 ? 0 : -EINVAL; } static void tgu_set_reg_number(struct tgu_drvdata *drvdata) @@ -131,16 +217,26 @@ static void tgu_set_steps(struct tgu_drvdata *drvdata) drvdata->num_step = TGU_DEVID_STEPS(devid); } +static void tgu_set_conditions(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + drvdata->num_condition_decode = TGU_DEVID_CONDITIONS(devid); +} + static int tgu_enable(struct device *dev) { struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + int ret; guard(spinlock)(&drvdata->lock); - drvdata->enabled = true; - tgu_write_all_hw_regs(drvdata); + ret = tgu_write_all_hw_regs(drvdata); + if (!ret) + drvdata->enabled = true; - return 0; + return ret; } static void tgu_do_disable(struct tgu_drvdata *drvdata) @@ -262,6 +358,14 @@ static const struct attribute_group *tgu_attr_groups[] = { PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1), PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2), PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(0), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(1), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(2), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(4), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -269,8 +373,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority; - size_t priority_size; + unsigned int *priority, *condition; + size_t priority_size, condition_size; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -288,6 +392,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) tgu_set_reg_number(drvdata); tgu_set_steps(drvdata); + tgu_set_conditions(drvdata); ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); if (ret) { @@ -310,6 +415,16 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata->value_table->priority = priority; + condition_size = drvdata->num_condition_decode * drvdata->num_step; + + condition = devm_kcalloc(dev, condition_size, + sizeof(*(drvdata->value_table->condition_decode)), + GFP_KERNEL); + if (!condition) + return -ENOMEM; + + drvdata->value_table->condition_decode = condition; + drvdata->enabled = false; pm_runtime_put(&adev->dev); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index f994d83acb1d6..56e4161a8bc21 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -16,6 +16,8 @@ ((int)FIELD_GET(GENMASK(17, 10), devid_val)) #define TGU_DEVID_STEPS(devid_val) \ ((int)FIELD_GET(GENMASK(6, 3), devid_val)) +#define TGU_DEVID_CONDITIONS(devid_val) \ + ((int)FIELD_GET(GENMASK(2, 0), devid_val)) #define TGU_BITS_PER_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -49,6 +51,7 @@ */ #define STEP_OFFSET 0x1D8 #define PRIORITY_START_OFFSET 0x0074 +#define CONDITION_DECODE_OFFSET 0x0050 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -57,6 +60,9 @@ (PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\ REG_OFFSET * reg + STEP_OFFSET * step) +#define CONDITION_DECODE_STEP(step, decode) \ + (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) + #define tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -68,6 +74,8 @@ #define STEP_PRIORITY(step_index, reg_num, priority) \ tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \ reg_num) +#define STEP_DECODE(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ @@ -91,6 +99,14 @@ NULL \ } +#define STEP_DECODE_LIST(n) \ + {STEP_DECODE(n, 0), \ + STEP_DECODE(n, 1), \ + STEP_DECODE(n, 2), \ + STEP_DECODE(n, 3), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -98,11 +114,19 @@ .name = "step" #step "_priority" #priority \ }) +#define CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_DECODE_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_decode" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, TGU_PRIORITY2, TGU_PRIORITY3, + TGU_CONDITION_DECODE, }; /* Maximum priority that TGU supports */ @@ -117,6 +141,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; + unsigned int *condition_decode; }; static inline void TGU_LOCK(void __iomem *addr) @@ -146,6 +171,7 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @value_table: Store given value based on relevant parameters * @num_reg: Maximum number of registers * @num_step: Maximum step size + * @num_condition_decode: Maximum number of condition_decode * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -160,6 +186,7 @@ struct tgu_drvdata { struct value_table *value_table; int num_reg; int num_step; + int num_condition_decode; }; #endif From 470d68721620cbc69afe5a294ffe08a77166a449 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:34 -0700 Subject: [PATCH 0054/1058] FROMLIST: qcom-tgu: Add support to configure next action Add "select" node for each step to determine if another step is taken, trigger(s) are generated, counters/timers incremented/decremented, etc. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-6-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 +++ drivers/hwtracing/qcom/tgu.c | 53 ++++++++++++++++++- drivers/hwtracing/qcom/tgu.h | 26 +++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 4ef0d696d3d0e..786cb852bbe51 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -21,3 +21,10 @@ KernelVersion: 7.1 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the decode mode with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_select/reg[0:3] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the next action with specific step for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 937211923d937..fefe932059cbb 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -29,6 +29,9 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, case TGU_CONDITION_DECODE: return step_index * (drvdata->num_condition_decode) + reg_index; + case TGU_CONDITION_SELECT: + return step_index * (drvdata->num_condition_select) + + reg_index; default: break; } @@ -71,6 +74,9 @@ static ssize_t tgu_dataset_show(struct device *dev, case TGU_CONDITION_DECODE: return sysfs_emit(buf, "0x%x\n", drvdata->value_table->condition_decode[index]); + case TGU_CONDITION_SELECT: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_select[index]); default: break; } @@ -112,6 +118,10 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_drvdata->value_table->condition_decode[index] = val; ret = size; break; + case TGU_CONDITION_SELECT: + tgu_drvdata->value_table->condition_select[index] = val; + ret = size; + break; default: ret = -EINVAL; break; @@ -146,6 +156,13 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->reg_num < drvdata->num_condition_decode) return attr->mode; break; + case TGU_CONDITION_SELECT: + /* 'default' register is at the end of 'select' region */ + if (tgu_attr->reg_num == drvdata->num_condition_select - 1) + attr->name = "default"; + if (tgu_attr->reg_num < drvdata->num_condition_select) + return attr->mode; + break; default: break; } @@ -184,6 +201,18 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) drvdata->base + CONDITION_DECODE_STEP(i, j)); } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_select; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_SELECT, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_select[index], + drvdata->base + CONDITION_SELECT_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); exit: @@ -223,6 +252,8 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) devid = readl(drvdata->base + TGU_DEVID); drvdata->num_condition_decode = TGU_DEVID_CONDITIONS(devid); + /* select region has an additional 'default' register */ + drvdata->num_condition_select = TGU_DEVID_CONDITIONS(devid) + 1; } static int tgu_enable(struct device *dev) @@ -366,6 +397,14 @@ static const struct attribute_group *tgu_attr_groups[] = { CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5), CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6), CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(0), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(1), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(2), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(3), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(4), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -373,8 +412,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority, *condition; - size_t priority_size, condition_size; + unsigned int *priority, *condition, *select; + size_t priority_size, condition_size, select_size; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -425,6 +464,16 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata->value_table->condition_decode = condition; + select_size = drvdata->num_condition_select * drvdata->num_step; + + select = devm_kcalloc(dev, select_size, + sizeof(*(drvdata->value_table->condition_select)), + GFP_KERNEL); + if (!select) + return -ENOMEM; + + drvdata->value_table->condition_select = select; + drvdata->enabled = false; pm_runtime_put(&adev->dev); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index 56e4161a8bc21..c61aa8dc51b0d 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -52,6 +52,7 @@ #define STEP_OFFSET 0x1D8 #define PRIORITY_START_OFFSET 0x0074 #define CONDITION_DECODE_OFFSET 0x0050 +#define CONDITION_SELECT_OFFSET 0x0060 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -63,6 +64,9 @@ #define CONDITION_DECODE_STEP(step, decode) \ (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) +#define CONDITION_SELECT_STEP(step, select) \ + (CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step) + #define tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -76,6 +80,8 @@ reg_num) #define STEP_DECODE(step_index, reg_num) \ tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) +#define STEP_SELECT(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num) #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ @@ -107,6 +113,15 @@ NULL \ } +#define STEP_SELECT_LIST(n) \ + {STEP_SELECT(n, 0), \ + STEP_SELECT(n, 1), \ + STEP_SELECT(n, 2), \ + STEP_SELECT(n, 3), \ + STEP_SELECT(n, 4), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -121,12 +136,20 @@ .name = "step" #step "_condition_decode" \ }) +#define CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_SELECT_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_select" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, TGU_PRIORITY2, TGU_PRIORITY3, TGU_CONDITION_DECODE, + TGU_CONDITION_SELECT, }; /* Maximum priority that TGU supports */ @@ -142,6 +165,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; unsigned int *condition_decode; + unsigned int *condition_select; }; static inline void TGU_LOCK(void __iomem *addr) @@ -172,6 +196,7 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @num_reg: Maximum number of registers * @num_step: Maximum step size * @num_condition_decode: Maximum number of condition_decode + * @num_condition_select: Maximum number of condition_select * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -187,6 +212,7 @@ struct tgu_drvdata { int num_reg; int num_step; int num_condition_decode; + int num_condition_select; }; #endif From 6e0791120fb80804fc140b7179b160855df31895 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:35 -0700 Subject: [PATCH 0055/1058] FROMLIST: qcom-tgu: Add timer/counter functionality for TGU Add counter and timer node for each step which could be programed if they are to be utilized in trigger event/sequence. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-7-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 14 +++ drivers/hwtracing/qcom/tgu.c | 116 +++++++++++++++++- drivers/hwtracing/qcom/tgu.h | 57 +++++++++ 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 786cb852bbe51..7a3573e03e27d 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -28,3 +28,17 @@ KernelVersion: 7.1 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the next action with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_timer/reg[0:1] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the timer value with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_counter/reg[0:1] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the counter value with specific step for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index fefe932059cbb..6d5bf2621cb05 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -32,6 +32,10 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, case TGU_CONDITION_SELECT: return step_index * (drvdata->num_condition_select) + reg_index; + case TGU_COUNTER: + return step_index * (drvdata->num_counter) + reg_index; + case TGU_TIMER: + return step_index * (drvdata->num_timer) + reg_index; default: break; } @@ -77,6 +81,12 @@ static ssize_t tgu_dataset_show(struct device *dev, case TGU_CONDITION_SELECT: return sysfs_emit(buf, "0x%x\n", drvdata->value_table->condition_select[index]); + case TGU_TIMER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->timer[index]); + case TGU_COUNTER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->counter[index]); default: break; } @@ -122,6 +132,14 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_drvdata->value_table->condition_select[index] = val; ret = size; break; + case TGU_TIMER: + tgu_drvdata->value_table->timer[index] = val; + ret = size; + break; + case TGU_COUNTER: + tgu_drvdata->value_table->counter[index] = val; + ret = size; + break; default: ret = -EINVAL; break; @@ -163,6 +181,18 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->reg_num < drvdata->num_condition_select) return attr->mode; break; + case TGU_COUNTER: + if (!drvdata->num_counter) + break; + if (tgu_attr->reg_num < drvdata->num_counter) + return attr->mode; + break; + case TGU_TIMER: + if (!drvdata->num_timer) + break; + if (tgu_attr->reg_num < drvdata->num_timer) + return attr->mode; + break; default: break; } @@ -213,6 +243,30 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) drvdata->base + CONDITION_SELECT_STEP(i, j)); } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_timer; j++) { + index = check_array_location(drvdata, i, TGU_TIMER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->timer[index], + drvdata->base + TIMER_COMPARE_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_counter; j++) { + index = check_array_location(drvdata, i, TGU_COUNTER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->counter[index], + drvdata->base + COUNTER_COMPARE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); exit: @@ -256,6 +310,27 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) drvdata->num_condition_select = TGU_DEVID_CONDITIONS(devid) + 1; } +static void tgu_set_timer_counter(struct tgu_drvdata *drvdata) +{ + int num_timers = 0, num_counters = 0; + u32 devid2; + + devid2 = readl(drvdata->base + CORESIGHT_DEVID2); + + if (TGU_DEVID2_TIMER0(devid2)) + num_timers++; + if (TGU_DEVID2_TIMER1(devid2)) + num_timers++; + + if (TGU_DEVID2_COUNTER0(devid2)) + num_counters++; + if (TGU_DEVID2_COUNTER1(devid2)) + num_counters++; + + drvdata->num_timer = num_timers; + drvdata->num_counter = num_counters; +} + static int tgu_enable(struct device *dev) { struct tgu_drvdata *drvdata = dev_get_drvdata(dev); @@ -405,6 +480,22 @@ static const struct attribute_group *tgu_attr_groups[] = { CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5), CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6), CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7), + TIMER_ATTRIBUTE_GROUP_INIT(0), + TIMER_ATTRIBUTE_GROUP_INIT(1), + TIMER_ATTRIBUTE_GROUP_INIT(2), + TIMER_ATTRIBUTE_GROUP_INIT(3), + TIMER_ATTRIBUTE_GROUP_INIT(4), + TIMER_ATTRIBUTE_GROUP_INIT(5), + TIMER_ATTRIBUTE_GROUP_INIT(6), + TIMER_ATTRIBUTE_GROUP_INIT(7), + COUNTER_ATTRIBUTE_GROUP_INIT(0), + COUNTER_ATTRIBUTE_GROUP_INIT(1), + COUNTER_ATTRIBUTE_GROUP_INIT(2), + COUNTER_ATTRIBUTE_GROUP_INIT(3), + COUNTER_ATTRIBUTE_GROUP_INIT(4), + COUNTER_ATTRIBUTE_GROUP_INIT(5), + COUNTER_ATTRIBUTE_GROUP_INIT(6), + COUNTER_ATTRIBUTE_GROUP_INIT(7), NULL, }; @@ -412,8 +503,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority, *condition, *select; - size_t priority_size, condition_size, select_size; + unsigned int *priority, *condition, *select, *timer, *counter; + size_t priority_size, condition_size, select_size, timer_size, counter_size; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -432,6 +523,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) tgu_set_reg_number(drvdata); tgu_set_steps(drvdata); tgu_set_conditions(drvdata); + tgu_set_timer_counter(drvdata); ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); if (ret) { @@ -474,6 +566,26 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata->value_table->condition_select = select; + timer_size = drvdata->num_step * drvdata->num_timer; + + timer = devm_kcalloc(dev, timer_size, + sizeof(*(drvdata->value_table->timer)), + GFP_KERNEL); + if (!timer) + return -ENOMEM; + + drvdata->value_table->timer = timer; + + counter_size = drvdata->num_step * drvdata->num_counter; + + counter = devm_kcalloc(dev, counter_size, + sizeof(*(drvdata->value_table->counter)), + GFP_KERNEL); + if (!counter) + return -ENOMEM; + + drvdata->value_table->counter = counter; + drvdata->enabled = false; pm_runtime_put(&adev->dev); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index c61aa8dc51b0d..1bcbc99169def 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -11,6 +11,7 @@ #define TGU_LAR 0xfb0 #define TGU_UNLOCK_OFFSET 0xc5acce55 #define TGU_DEVID 0xfc8 +#define CORESIGHT_DEVID2 0xfc0 #define TGU_DEVID_SENSE_INPUT(devid_val) \ ((int)FIELD_GET(GENMASK(17, 10), devid_val)) @@ -18,6 +19,16 @@ ((int)FIELD_GET(GENMASK(6, 3), devid_val)) #define TGU_DEVID_CONDITIONS(devid_val) \ ((int)FIELD_GET(GENMASK(2, 0), devid_val)) +#define TGU_DEVID2_TIMER0(devid_val) \ + ((int)FIELD_GET(GENMASK(23, 18), devid_val)) +#define TGU_DEVID2_TIMER1(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 13), devid_val)) +#define TGU_DEVID2_COUNTER0(devid_val) \ + ((int)FIELD_GET(GENMASK(11, 6), devid_val)) +#define TGU_DEVID2_COUNTER1(devid_val) \ + ((int)FIELD_GET(GENMASK(5, 0), devid_val)) + + #define TGU_BITS_PER_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -53,6 +64,8 @@ #define PRIORITY_START_OFFSET 0x0074 #define CONDITION_DECODE_OFFSET 0x0050 #define CONDITION_SELECT_OFFSET 0x0060 +#define TIMER_START_OFFSET 0x0040 +#define COUNTER_START_OFFSET 0x0048 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -67,6 +80,12 @@ #define CONDITION_SELECT_STEP(step, select) \ (CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step) +#define TIMER_COMPARE_STEP(step, timer) \ + (TIMER_START_OFFSET + REG_OFFSET * timer + STEP_OFFSET * step) + +#define COUNTER_COMPARE_STEP(step, counter) \ + (COUNTER_START_OFFSET + REG_OFFSET * counter + STEP_OFFSET * step) + #define tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -82,6 +101,10 @@ tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) #define STEP_SELECT(step_index, reg_num) \ tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num) +#define STEP_TIMER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_TIMER, reg_num) +#define STEP_COUNTER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_COUNTER, reg_num) #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ @@ -122,6 +145,18 @@ NULL \ } +#define STEP_TIMER_LIST(n) \ + {STEP_TIMER(n, 0), \ + STEP_TIMER(n, 1), \ + NULL \ + } + +#define STEP_COUNTER_LIST(n) \ + {STEP_COUNTER(n, 0), \ + STEP_COUNTER(n, 1), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -143,6 +178,20 @@ .name = "step" #step "_condition_select" \ }) +#define TIMER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_TIMER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_timer" \ + }) + +#define COUNTER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_COUNTER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_counter" \ + }) + enum operation_index { TGU_PRIORITY0, TGU_PRIORITY1, @@ -150,6 +199,8 @@ enum operation_index { TGU_PRIORITY3, TGU_CONDITION_DECODE, TGU_CONDITION_SELECT, + TGU_TIMER, + TGU_COUNTER, }; /* Maximum priority that TGU supports */ @@ -166,6 +217,8 @@ struct value_table { unsigned int *priority; unsigned int *condition_decode; unsigned int *condition_select; + unsigned int *timer; + unsigned int *counter; }; static inline void TGU_LOCK(void __iomem *addr) @@ -197,6 +250,8 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @num_step: Maximum step size * @num_condition_decode: Maximum number of condition_decode * @num_condition_select: Maximum number of condition_select + * @num_timer: Maximum number of timers + * @num_counter: Maximum number of counters * * This structure defines the data associated with a TGU device, * including its base address, device pointers, clock, spinlock for @@ -213,6 +268,8 @@ struct tgu_drvdata { int num_step; int num_condition_decode; int num_condition_select; + int num_timer; + int num_counter; }; #endif From 9f68e4ad398d56dc79aacd8765cc378c166a81b2 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Fri, 17 Apr 2026 00:33:36 -0700 Subject: [PATCH 0056/1058] FROMLIST: qcom-tgu: Add reset node to initialize Add reset node to initialize the value of priority/condition_decode/condition_select/timer/counter nodes. Link: https://lore.kernel.org/linux-arm-msm/20260417073336.2712426-8-songwei.chai@oss.qualcomm.com/ Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 ++ drivers/hwtracing/qcom/tgu.c | 74 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 7a3573e03e27d..a6b6019c8ef17 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -42,3 +42,10 @@ KernelVersion: 7.1 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the counter value with specific step for TGU. + +What: /sys/bus/amba/devices//reset_tgu +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (Write) Write 1 to reset the dataset for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 6d5bf2621cb05..9fb51f2a912f9 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -420,8 +420,82 @@ static ssize_t enable_tgu_store(struct device *dev, } static DEVICE_ATTR_RW(enable_tgu); +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */ +static ssize_t reset_tgu_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct value_table *vt = drvdata->value_table; + u32 *cond_decode = drvdata->value_table->condition_decode; + unsigned long value; + int i, j, ret; + + if (kstrtoul(buf, 0, &value) || value != 1) + return -EINVAL; + + spin_lock(&drvdata->lock); + if (!drvdata->enabled) { + spin_unlock(&drvdata->lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret) + return ret; + spin_lock(&drvdata->lock); + } + + tgu_do_disable(drvdata); + + if (vt->priority) { + size_t size = MAX_PRIORITY * drvdata->num_step * + drvdata->num_reg * sizeof(unsigned int); + memset(vt->priority, 0, size); + } + + if (vt->condition_decode) { + size_t size = drvdata->num_condition_decode * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_decode, 0, size); + } + + /* Initialize all condition registers to NOT(value=0x1000000) */ + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_decode; j++) { + cond_decode[calculate_array_location(drvdata, i, + TGU_CONDITION_DECODE, j)] = 0x1000000; + } + } + + if (vt->condition_select) { + size_t size = drvdata->num_condition_select * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_select, 0, size); + } + + if (vt->timer) { + size_t size = (drvdata->num_step) * (drvdata->num_timer) * + sizeof(unsigned int); + memset(vt->timer, 0, size); + } + + if (vt->counter) { + size_t size = (drvdata->num_step) * (drvdata->num_counter) * + sizeof(unsigned int); + memset(vt->counter, 0, size); + } + + spin_unlock(&drvdata->lock); + + dev_dbg(dev, "Qualcomm-TGU reset complete\n"); + + pm_runtime_put(drvdata->dev); + + return size; +} +static DEVICE_ATTR_WO(reset_tgu); + static struct attribute *tgu_common_attrs[] = { &dev_attr_enable_tgu.attr, + &dev_attr_reset_tgu.attr, NULL, }; From f7b06ea023139319162185fe90d954e2a00d6e95 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:29 +0800 Subject: [PATCH 0057/1058] FROMLIST: coresight: cti: Convert trigger usage fields to dynamic Replace the fixed-size u32 fields in the cti_config and cti_trig_grp structure with dynamically allocated bitmaps and arrays. This allows memory to be allocated based on the actual number of triggers during probe time, reducing memory footprint and improving scalability for platforms with varying trigger counts. Also add a bounds check in cti_allocate_trig_con() to ensure the caller does not pass in/out signal counts larger than nr_trig_max. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-1-1c1694b6d8ed@oss.qualcomm.com/ Reviewed-by: Leo Yan Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 70 +++++++++++++++---- .../coresight/coresight-cti-platform.c | 26 ++++--- .../hwtracing/coresight/coresight-cti-sysfs.c | 14 ++-- drivers/hwtracing/coresight/coresight-cti.h | 12 ++-- 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index b2c9a4db13b4e..572798ab504c8 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -161,8 +161,8 @@ void cti_write_intack(struct device *dev, u32 ackval) /* DEVID[19:16] - number of CTM channels */ #define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) -static void cti_set_default_config(struct device *dev, - struct cti_drvdata *drvdata) +static int cti_set_default_config(struct device *dev, + struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; u32 devid; @@ -181,6 +181,31 @@ static void cti_set_default_config(struct device *dev, config->nr_trig_max = CTIINOUTEN_MAX; } + config->trig_in_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_in_use) + return -ENOMEM; + + config->trig_out_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_use) + return -ENOMEM; + + config->trig_out_filter = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_filter) + return -ENOMEM; + + config->ctiinen = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiinen) + return -ENOMEM; + + config->ctiouten = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiouten) + return -ENOMEM; + config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid); /* Most regs default to 0 as zalloc'ed except...*/ @@ -189,6 +214,7 @@ static void cti_set_default_config(struct device *dev, config->enable_req_count = 0; config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid); + return 0; } /* @@ -219,8 +245,10 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, cti_dev->nr_trig_con++; /* add connection usage bit info to overall info */ - drvdata->config.trig_in_use |= tc->con_in->used_mask; - drvdata->config.trig_out_use |= tc->con_out->used_mask; + bitmap_or(drvdata->config.trig_in_use, drvdata->config.trig_in_use, + tc->con_in->used_mask, drvdata->config.nr_trig_max); + bitmap_or(drvdata->config.trig_out_use, drvdata->config.trig_out_use, + tc->con_out->used_mask, drvdata->config.nr_trig_max); return 0; } @@ -231,6 +259,14 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, { struct cti_trig_con *tc = NULL; struct cti_trig_grp *in = NULL, *out = NULL; + struct cti_drvdata *drvdata = dev_get_drvdata(dev); + int n_trigs = drvdata->config.nr_trig_max; + + if (in_sigs > n_trigs || out_sigs > n_trigs) { + dev_err(dev, "trigger signal is out of range: in=%d out=%d nr_max=%d\n", + in_sigs, out_sigs, n_trigs); + return NULL; + } tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL); if (!tc) @@ -242,12 +278,20 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, if (!in) return NULL; + in->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!in->used_mask) + return NULL; + out = devm_kzalloc(dev, offsetof(struct cti_trig_grp, sig_types[out_sigs]), GFP_KERNEL); if (!out) return NULL; + out->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!out->used_mask) + return NULL; + tc->con_in = in; tc->con_out = out; tc->con_in->nr_sigs = in_sigs; @@ -263,7 +307,6 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) { int ret = 0; int n_trigs = drvdata->config.nr_trig_max; - u32 n_trig_mask = GENMASK(n_trigs - 1, 0); struct cti_trig_con *tc = NULL; /* @@ -274,8 +317,8 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) if (!tc) return -ENOMEM; - tc->con_in->used_mask = n_trig_mask; - tc->con_out->used_mask = n_trig_mask; + bitmap_fill(tc->con_in->used_mask, n_trigs); + bitmap_fill(tc->con_out->used_mask, n_trigs); ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default"); return ret; } @@ -288,7 +331,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - u32 trig_bitmask; u32 chan_bitmask; u32 reg_value; int reg_offset; @@ -298,18 +340,16 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, (trigger_idx >= config->nr_trig_max)) return -EINVAL; - trig_bitmask = BIT(trigger_idx); - /* ensure registered triggers and not out filtered */ if (direction == CTI_TRIG_IN) { - if (!(trig_bitmask & config->trig_in_use)) + if (!(test_bit(trigger_idx, config->trig_in_use))) return -EINVAL; } else { - if (!(trig_bitmask & config->trig_out_use)) + if (!(test_bit(trigger_idx, config->trig_out_use))) return -EINVAL; if ((config->trig_filter_enable) && - (config->trig_out_filter & trig_bitmask)) + test_bit(trigger_idx, config->trig_out_filter)) return -EINVAL; } @@ -687,7 +727,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) raw_spin_lock_init(&drvdata->spinlock); /* initialise CTI driver config values */ - cti_set_default_config(dev, drvdata); + ret = cti_set_default_config(dev, drvdata); + if (ret) + return ret; pdata = coresight_cti_get_platform_data(dev); if (IS_ERR(pdata)) { diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index d6d5388705c3e..ba5a7e4b6bff0 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -136,8 +136,8 @@ static int cti_plat_create_v8_etm_connection(struct device *dev, goto create_v8_etm_out; /* build connection data */ - tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */ - tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */ + bitmap_set(tc->con_in->used_mask, 4, 4); /* sigs <4,5,6,7> */ + bitmap_set(tc->con_out->used_mask, 4, 4); /* sigs <4,5,6,7> */ /* * The EXTOUT type signals from the ETM are connected to a set of input @@ -194,10 +194,10 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* Set the v8 PE CTI connection data */ - tc->con_in->used_mask = 0x3; /* sigs <0 1> */ + bitmap_set(tc->con_in->used_mask, 0, 2); /* sigs <0 1> */ tc->con_in->sig_types[0] = PE_DBGTRIGGER; tc->con_in->sig_types[1] = PE_PMUIRQ; - tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */ + bitmap_set(tc->con_out->used_mask, 0, 3); /* sigs <0 1 2 > */ tc->con_out->sig_types[0] = PE_EDBGREQ; tc->con_out->sig_types[1] = PE_DBGRESTART; tc->con_out->sig_types[2] = PE_CTIIRQ; @@ -213,7 +213,7 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* filter pe_edbgreq - PE trigout sig <0> */ - drvdata->config.trig_out_filter |= 0x1; + set_bit(0, drvdata->config.trig_out_filter); of_create_v8_out: return ret; @@ -257,7 +257,7 @@ static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp, if (!err) { /* set the signal usage mask */ for (idx = 0; idx < tgrp->nr_sigs; idx++) - tgrp->used_mask |= BIT(values[idx]); + set_bit(values[idx], tgrp->used_mask); } kfree(values); @@ -316,24 +316,34 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, { struct cti_trig_grp *tg = NULL; int err = 0, nr_filter_sigs; + int nr_trigs = drvdata->config.nr_trig_max; nr_filter_sigs = cti_plat_count_sig_elements(fwnode, CTI_DT_FILTER_OUT_SIGS); if (nr_filter_sigs == 0) return 0; - if (nr_filter_sigs > drvdata->config.nr_trig_max) + if (nr_filter_sigs > nr_trigs) return -EINVAL; tg = kzalloc_obj(*tg); if (!tg) return -ENOMEM; + tg->used_mask = bitmap_zalloc(nr_trigs, GFP_KERNEL); + if (!tg->used_mask) { + kfree(tg); + return -ENOMEM; + } + tg->nr_sigs = nr_filter_sigs; err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); if (!err) - drvdata->config.trig_out_filter |= tg->used_mask; + bitmap_or(drvdata->config.trig_out_filter, + drvdata->config.trig_out_filter, + tg->used_mask, nr_trigs); + bitmap_free(tg->used_mask); kfree(tg); return err; } diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 3fe2c916d2288..2bbfa405cb6b0 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -719,12 +719,12 @@ static ssize_t trigout_filtered_show(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; int nr_trig_max = cfg->nr_trig_max; - unsigned long mask = cfg->trig_out_filter; + unsigned long *mask = cfg->trig_out_filter; - if (mask == 0) + if (bitmap_empty(mask, nr_trig_max)) return 0; - return sysfs_emit(buf, "%*pbl\n", nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", nr_trig_max, mask); } static DEVICE_ATTR_RO(trigout_filtered); @@ -931,9 +931,9 @@ static ssize_t trigin_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_in->used_mask; + unsigned long *mask = con->con_in->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } static ssize_t trigout_sig_show(struct device *dev, @@ -945,9 +945,9 @@ static ssize_t trigout_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_out->used_mask; + unsigned long *mask = con->con_out->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } /* convert a sig type id to a name */ diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index c5f9e79fabc60..ef079fc18b72a 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -68,7 +68,7 @@ struct fwnode_handle; */ struct cti_trig_grp { int nr_sigs; - u32 used_mask; + unsigned long *used_mask; int sig_types[]; }; @@ -145,17 +145,17 @@ struct cti_config { int enable_req_count; /* registered triggers and filtering */ - u32 trig_in_use; - u32 trig_out_use; - u32 trig_out_filter; + unsigned long *trig_in_use; + unsigned long *trig_out_use; + unsigned long *trig_out_filter; bool trig_filter_enable; u8 xtrig_rchan_sel; /* cti cross trig programmable regs */ u32 ctiappset; u8 ctiinout_sel; - u32 ctiinen[CTIINOUTEN_MAX]; - u32 ctiouten[CTIINOUTEN_MAX]; + u32 *ctiinen; + u32 *ctiouten; u32 ctigate; u32 asicctl; }; From 2ae6c18a2dec46211504ae78ccd442fb12564fe5 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:30 +0800 Subject: [PATCH 0058/1058] FROMLIST: coresight: cti: use __reg_addr() helper for register access Introduce a static inline __reg_addr(drvdata, off, index) helper in coresight-cti.h to compute MMIO addresses from a base offset and a per-trigger index, replacing the function-like CTIINEN(n)/CTIOUTEN(n) macros with base offsets and explicit index arithmetic. Add reg_addr and reg_index_addr convenience macros for zero-index and indexed access respectively. Convert cti_read_single_reg() and cti_write_single_reg() to static inline wrappers in coresight-cti.h, and add indexed variants cti_read_single_reg_index() / cti_write_single_reg_index() for callers that need explicit bank selection. Extend cs_off_attribute with a u32 index field and update coresight_cti_reg_show/store to use the attribute's index field directly. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-2-1c1694b6d8ed@oss.qualcomm.com/ Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 36 ++++----------- .../hwtracing/coresight/coresight-cti-sysfs.c | 17 ++++--- drivers/hwtracing/coresight/coresight-cti.h | 46 +++++++++++++++++-- drivers/hwtracing/coresight/coresight-priv.h | 4 +- 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 572798ab504c8..fa758c535ccbf 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -55,16 +55,17 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) /* write the CTI trigger registers */ for (i = 0; i < config->nr_trig_max; i++) { - writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i)); + writel_relaxed(config->ctiinen[i], + reg_index_addr(drvdata, CTIINEN, i)); writel_relaxed(config->ctiouten[i], - drvdata->base + CTIOUTEN(i)); + reg_index_addr(drvdata, CTIOUTEN, i)); } /* other regs */ - writel_relaxed(config->ctigate, drvdata->base + CTIGATE); + writel_relaxed(config->ctigate, reg_addr(drvdata, CTIGATE)); if (config->asicctl_impl) - writel_relaxed(config->asicctl, drvdata->base + ASICCTL); - writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET); + writel_relaxed(config->asicctl, reg_addr(drvdata, ASICCTL)); + writel_relaxed(config->ctiappset, reg_addr(drvdata, CTIAPPSET)); /* re-enable CTI */ writel_relaxed(1, drvdata->base + CTICONTROL); @@ -122,24 +123,6 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) return 0; } -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset) -{ - int val; - - CS_UNLOCK(drvdata->base); - val = readl_relaxed(drvdata->base + offset); - CS_LOCK(drvdata->base); - - return val; -} - -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) -{ - CS_UNLOCK(drvdata->base); - writel_relaxed(value, drvdata->base + offset); - CS_LOCK(drvdata->base); -} - void cti_write_intack(struct device *dev, u32 ackval) { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); @@ -333,7 +316,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, struct cti_config *config = &drvdata->config; u32 chan_bitmask; u32 reg_value; - int reg_offset; + u32 reg_offset; /* ensure indexes in range */ if ((channel_idx >= config->nr_ctm_channels) || @@ -355,8 +338,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* update the local register values */ chan_bitmask = BIT(channel_idx); - reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) : - CTIOUTEN(trigger_idx)); + reg_offset = (direction == CTI_TRIG_IN ? CTIINEN : CTIOUTEN); guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -376,7 +358,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, reg_offset, reg_value); + cti_write_single_reg_index(drvdata, reg_offset, trigger_idx, reg_value); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 2bbfa405cb6b0..6165866eaefe8 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -171,7 +171,7 @@ static ssize_t coresight_cti_reg_show(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - val = cti_read_single_reg(drvdata, cti_attr->off); + val = cti_read_single_reg_index(drvdata, cti_attr->off, cti_attr->index); pm_runtime_put_sync(dev->parent); return sysfs_emit(buf, "0x%x\n", val); @@ -192,7 +192,7 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - cti_write_single_reg(drvdata, cti_attr->off, val); + cti_write_single_reg_index(drvdata, cti_attr->off, cti_attr->index, val); pm_runtime_put_sync(dev->parent); return size; @@ -202,7 +202,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -211,7 +212,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, { \ __ATTR(name, 0644, coresight_cti_reg_show, \ coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -219,7 +221,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -386,7 +389,7 @@ static ssize_t inen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIINEN(index), val); + cti_write_single_reg_index(drvdata, CTIINEN, index, val); return size; } @@ -427,7 +430,7 @@ static ssize_t outen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIOUTEN(index), val); + cti_write_single_reg_index(drvdata, CTIOUTEN, index, val); return size; } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index ef079fc18b72a..634bdce5cdfd7 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -30,8 +30,8 @@ struct fwnode_handle; #define CTIAPPSET 0x014 #define CTIAPPCLEAR 0x018 #define CTIAPPPULSE 0x01C -#define CTIINEN(n) (0x020 + (4 * n)) -#define CTIOUTEN(n) (0x0A0 + (4 * n)) +#define CTIINEN 0x020 +#define CTIOUTEN 0x0A0 #define CTITRIGINSTATUS 0x130 #define CTITRIGOUTSTATUS 0x134 #define CTICHINSTATUS 0x138 @@ -217,8 +217,6 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode, int cti_disable(struct coresight_device *csdev, struct coresight_path *path); void cti_write_all_hw_regs(struct cti_drvdata *drvdata); void cti_write_intack(struct device *dev, u32 ackval); -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value); -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset); int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, enum cti_trig_dir direction, u32 channel_idx, u32 trigger_idx); @@ -231,6 +229,46 @@ struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); +static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + return drvdata->base + off + index * sizeof(u32); +} + +#define reg_addr(drvdata, off) __reg_addr((drvdata), (off), 0) +#define reg_index_addr(drvdata, off, i) __reg_addr((drvdata), (off), (i)) + +static inline u32 cti_read_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + u32 val; + + CS_UNLOCK(drvdata->base); + val = readl_relaxed(reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); + + return val; +} + +static inline u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off) +{ + return cti_read_single_reg_index(drvdata, off, 0); +} + +static inline void cti_write_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index, u32 value) +{ + CS_UNLOCK(drvdata->base); + writel_relaxed(value, reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); +} + +static inline void cti_write_single_reg(struct cti_drvdata *drvdata, + u32 off, u32 value) +{ + cti_write_single_reg_index(drvdata, off, 0, value); +} + /* Check if a cti device is enabled */ static inline bool cti_is_active(struct cti_config *cfg) { diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 854c0a3cb080c..46284eb9b300e 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -58,6 +58,7 @@ struct cs_pair_attribute { struct cs_off_attribute { struct device_attribute attr; u32 off; + u32 index; }; ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf); @@ -67,7 +68,8 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_simple_show32, NULL), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) From dcdbf2cbf29361828126e9996038b115108215f1 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:31 +0800 Subject: [PATCH 0059/1058] FROMLIST: coresight: cti: add Qualcomm extended CTI identification and quirks Qualcomm implements an extended variant of the ARM CoreSight CTI with a different register layout and vendor-specific behavior. While the programming model remains largely compatible, the register offsets differ from the standard ARM CTI and require explicit handling. Detect Qualcomm CTIs via the DEVARCH register and record this in the CTI driver data. Introduce a small mapping layer to translate standard CTI register offsets to Qualcomm-specific offsets, allowing the rest of the driver to use a common register access path. Additionally, handle a Qualcomm-specific quirk where the hardware does not implement the CoreSight Claim tag protocol. Instead of clearing the CLAIMSET register at probe time, bypass the claim/disclaim operations entirely for Qualcomm CTIs by wrapping coresight_claim_device(), coresight_disclaim_device_unlocked() and coresight_clear_self_claim_tag() in thin helpers that early-return when is_qcom_cti is set. No functional change is intended for standard ARM CTI devices. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-3-1c1694b6d8ed@oss.qualcomm.com/ Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 47 ++++++++++++-- drivers/hwtracing/coresight/coresight-cti.h | 64 ++++++++++++++++++- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index fa758c535ccbf..5b83dd4e603bd 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -73,6 +73,35 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) CS_LOCK(drvdata->base); } +/* + * Qualcomm CTIs do not implement the CoreSight Claim tag protocol, so + * bypass coresight_clear_self_claim_tag() for them. + */ +static void cti_clear_self_claim_tag(struct cti_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_clear_self_claim_tag(csa); +} + +static int cti_claim_device(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return 0; + + return coresight_claim_device(drvdata->csdev); +} + +static void cti_unclaim_device_unlocked(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_disclaim_device_unlocked(drvdata->csdev); +} + /* write regs to hardware and enable */ static int cti_enable_hw(struct cti_drvdata *drvdata) { @@ -86,7 +115,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) goto cti_state_unchanged; /* claim the device */ - rc = coresight_claim_device(drvdata->csdev); + rc = cti_claim_device(drvdata); if (rc) return rc; @@ -101,7 +130,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct coresight_device *csdev = drvdata->csdev; guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -118,7 +146,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) /* disable CTI */ writel_relaxed(0, drvdata->base + CTICONTROL); - coresight_disclaim_device_unlocked(csdev); + cti_unclaim_device_unlocked(drvdata); CS_LOCK(drvdata->base); return 0; } @@ -144,6 +172,9 @@ void cti_write_intack(struct device *dev, u32 ackval) /* DEVID[19:16] - number of CTM channels */ #define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) +/* DEVARCH[31:21] - ARCHITECT */ +#define CTI_DEVARCH_ARCHITECT(devarch_val) ((int)BMVAL(devarch_val, 21, 31)) + static int cti_set_default_config(struct device *dev, struct cti_drvdata *drvdata) { @@ -684,6 +715,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc cti_desc = { 0 }; struct coresight_platform_data *pdata = NULL; struct resource *res = &adev->res; + u32 devarch; /* driver data*/ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -708,6 +740,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) raw_spin_lock_init(&drvdata->spinlock); + devarch = readl_relaxed(drvdata->base + CORESIGHT_DEVARCH); + if (CTI_DEVARCH_ARCHITECT(devarch) == QCOM_ARCHITECT) + drvdata->is_qcom_cti = true; + /* initialise CTI driver config values */ ret = cti_set_default_config(dev, drvdata); if (ret) @@ -753,7 +789,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) cti_desc.groups = drvdata->ctidev.con_groups; cti_desc.dev = dev; - coresight_clear_self_claim_tag(&cti_desc.access); + cti_clear_self_claim_tag(drvdata, &cti_desc.access); drvdata->csdev = coresight_register(&cti_desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); @@ -767,7 +803,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* all done - dec pm refcount */ pm_runtime_put(&adev->dev); - dev_info(&drvdata->csdev->dev, "CTI initialized\n"); + dev_info(&drvdata->csdev->dev, + "%sCTI initialized\n", drvdata->is_qcom_cti ? "QCOM " : ""); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index 634bdce5cdfd7..4b6fd6b551142 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -54,10 +54,36 @@ struct fwnode_handle; /* * CTI CSSoc 600 has a max of 32 trigger signals per direction. * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def. + * QCOM CTI support up to 128 trigger signals per direction. * Max of in and out defined in the DEVID register. * - pick up actual number used from .dts parameters if present. */ -#define CTIINOUTEN_MAX 32 +#define CTIINOUTEN_MAX 128 + +/* QCOM CTI extension */ +#define QCOM_ARCHITECT 0x477 + +#define QCOM_CTIINTACK 0x020 +#define QCOM_CTIAPPSET 0x004 +#define QCOM_CTIAPPCLEAR 0x008 +#define QCOM_CTIAPPPULSE 0x00C +#define QCOM_CTIINEN 0x400 +#define QCOM_CTIOUTEN 0x800 +#define QCOM_CTITRIGINSTATUS 0x040 +#define QCOM_CTITRIGOUTSTATUS 0x060 +#define QCOM_CTICHINSTATUS 0x080 +#define QCOM_CTICHOUTSTATUS 0x084 +#define QCOM_CTIGATE 0x088 +#define QCOM_ASICCTL 0x08C +/* Integration test registers */ +#define QCOM_ITCHINACK 0xE70 +#define QCOM_ITTRIGINACK 0xE80 +#define QCOM_ITCHOUT 0xE74 +#define QCOM_ITTRIGOUT 0xEA0 +#define QCOM_ITCHOUTACK 0xE78 +#define QCOM_ITTRIGOUTACK 0xEC0 +#define QCOM_ITCHIN 0xE7C +#define QCOM_ITTRIGIN 0xEE0 /** * Group of related trigger signals @@ -168,6 +194,9 @@ struct cti_config { * @spinlock: Control data access to one at a time. * @config: Configuration data for this CTI device. * @node: List entry of this device in the list of CTI devices. + * @is_qcom_cti: True if this CTI is a Qualcomm vendor-specific + * variant that requires register offset translation + * via cti_qcom_reg_off(). */ struct cti_drvdata { void __iomem *base; @@ -176,6 +205,7 @@ struct cti_drvdata { raw_spinlock_t spinlock; struct cti_config config; struct list_head node; + bool is_qcom_cti; }; /* @@ -229,9 +259,41 @@ struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); +static inline u32 cti_qcom_reg_off(u32 offset) +{ + switch (offset) { + case CTIINTACK: return QCOM_CTIINTACK; + case CTIAPPSET: return QCOM_CTIAPPSET; + case CTIAPPCLEAR: return QCOM_CTIAPPCLEAR; + case CTIAPPPULSE: return QCOM_CTIAPPPULSE; + case CTIINEN: return QCOM_CTIINEN; + case CTIOUTEN: return QCOM_CTIOUTEN; + case CTITRIGINSTATUS: return QCOM_CTITRIGINSTATUS; + case CTITRIGOUTSTATUS: return QCOM_CTITRIGOUTSTATUS; + case CTICHINSTATUS: return QCOM_CTICHINSTATUS; + case CTICHOUTSTATUS: return QCOM_CTICHOUTSTATUS; + case CTIGATE: return QCOM_CTIGATE; + case ASICCTL: return QCOM_ASICCTL; + case ITCHINACK: return QCOM_ITCHINACK; + case ITTRIGINACK: return QCOM_ITTRIGINACK; + case ITCHOUT: return QCOM_ITCHOUT; + case ITTRIGOUT: return QCOM_ITTRIGOUT; + case ITCHOUTACK: return QCOM_ITCHOUTACK; + case ITTRIGOUTACK: return QCOM_ITTRIGOUTACK; + case ITCHIN: return QCOM_ITCHIN; + case ITTRIGIN: return QCOM_ITTRIGIN; + + default: + return offset; + } +} + static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata, u32 off, u32 index) { + if (unlikely(drvdata->is_qcom_cti)) + off = cti_qcom_reg_off(off); + return drvdata->base + off + index * sizeof(u32); } From 1af00cda9afd8eb5bfa1d5d478f819c17f07c6e2 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:32 +0800 Subject: [PATCH 0060/1058] FROMLIST: coresight: cti: expose banked sysfs registers for Qualcomm extended CTI Qualcomm extended CTI implements banked trigger status and integration registers, where each bank covers 32 triggers. Multiple instances of these registers are required to expose the full trigger space. Add coresight_cti_reg_index(), coresight_cti_reg_rw_index(), and coresight_cti_reg_wo_index() macros that carry the bank index in the cs_off_attribute.index field, keeping the base offset and index separate rather than encoding them together. Add static sysfs entries for the banked CTI registers and control their visibility based on the underlying hardware configuration. Visibility is determined by comparing the attribute's index against the number of banks implied by nr_trig_max (32 triggers per bank). Registers beyond the hardware capacity are hidden, preserving the existing ABI on standard ARM CTIs while exposing the full register set on Qualcomm CTIs. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-4-1c1694b6d8ed@oss.qualcomm.com/ Reviewed-by: Leo Yan Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-sysfs.c | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 6165866eaefe8..175f20d69232d 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -207,6 +207,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + #define coresight_cti_reg_rw(name, offset) \ (&((struct cs_off_attribute[]) { \ { \ @@ -217,6 +226,16 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_rw_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0644, coresight_cti_reg_show, \ + coresight_cti_reg_store), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + #define coresight_cti_reg_wo(name, offset) \ (&((struct cs_off_attribute[]) { \ { \ @@ -226,6 +245,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_wo_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + /* coresight management registers */ static struct attribute *coresight_cti_mgmt_attrs[] = { coresight_cti_reg(devaff0, CTIDEVAFF0), @@ -515,18 +543,36 @@ static struct attribute *coresight_cti_regs_attrs[] = { &dev_attr_appclear.attr, &dev_attr_apppulse.attr, coresight_cti_reg(triginstatus, CTITRIGINSTATUS), + coresight_cti_reg_index(triginstatus1, CTITRIGINSTATUS, 1), + coresight_cti_reg_index(triginstatus2, CTITRIGINSTATUS, 2), + coresight_cti_reg_index(triginstatus3, CTITRIGINSTATUS, 3), coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS), + coresight_cti_reg_index(trigoutstatus1, CTITRIGOUTSTATUS, 1), + coresight_cti_reg_index(trigoutstatus2, CTITRIGOUTSTATUS, 2), + coresight_cti_reg_index(trigoutstatus3, CTITRIGOUTSTATUS, 3), coresight_cti_reg(chinstatus, CTICHINSTATUS), coresight_cti_reg(choutstatus, CTICHOUTSTATUS), #ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL), coresight_cti_reg(ittrigin, ITTRIGIN), + coresight_cti_reg_index(ittrigin1, ITTRIGIN, 1), + coresight_cti_reg_index(ittrigin2, ITTRIGIN, 2), + coresight_cti_reg_index(ittrigin3, ITTRIGIN, 3), coresight_cti_reg(itchin, ITCHIN), coresight_cti_reg_rw(ittrigout, ITTRIGOUT), + coresight_cti_reg_rw_index(ittrigout1, ITTRIGOUT, 1), + coresight_cti_reg_rw_index(ittrigout2, ITTRIGOUT, 2), + coresight_cti_reg_rw_index(ittrigout3, ITTRIGOUT, 3), coresight_cti_reg_rw(itchout, ITCHOUT), coresight_cti_reg(itchoutack, ITCHOUTACK), coresight_cti_reg(ittrigoutack, ITTRIGOUTACK), + coresight_cti_reg_index(ittrigoutack1, ITTRIGOUTACK, 1), + coresight_cti_reg_index(ittrigoutack2, ITTRIGOUTACK, 2), + coresight_cti_reg_index(ittrigoutack3, ITTRIGOUTACK, 3), coresight_cti_reg_wo(ittriginack, ITTRIGINACK), + coresight_cti_reg_wo_index(ittriginack1, ITTRIGINACK, 1), + coresight_cti_reg_wo_index(ittriginack2, ITTRIGINACK, 2), + coresight_cti_reg_wo_index(ittriginack3, ITTRIGINACK, 3), coresight_cti_reg_wo(itchinack, ITCHINACK), #endif NULL, @@ -537,10 +583,22 @@ static umode_t coresight_cti_regs_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct device_attribute *dev_attr; + struct cs_off_attribute *cti_attr; + int max_bank; if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl) return 0; + dev_attr = container_of(attr, struct device_attribute, attr); + if (dev_attr->show == coresight_cti_reg_show || + dev_attr->store == coresight_cti_reg_store) { + cti_attr = container_of(dev_attr, struct cs_off_attribute, attr); + max_bank = DIV_ROUND_UP(drvdata->config.nr_trig_max, 32); + if (cti_attr->index >= max_bank) + return 0; + } + return attr->mode; } From 21cc975dd4b30f3b638ccfa1b15f8077dcf7c9d8 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:33 +0800 Subject: [PATCH 0061/1058] FROMLIST: coresight: cti: document banked and missing base CTI sysfs registers Document the new sysfs entries triginstatus[1-3], trigoutstatus[1-3], ittrigin[1-3], ittrigout[1-3], ittrigoutack[1-3] and ittriginack[1-3] in the coresight-cti ABI documentation. Also document the previously undocumented base integration test registers itctrl, itchin, itchinack, ittrigin, ittriginack, itchout, itchoutack, ittrigout and ittrigoutack, which were introduced in kernel version 5.7. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-5-1c1694b6d8ed@oss.qualcomm.com/ Signed-off-by: Yingchao Deng --- .../testing/sysfs-bus-coresight-devices-cti | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti index a2aef7f5a6d74..9d7831ac455b8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti @@ -128,12 +128,102 @@ KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of input trigger signals +What: /sys/bus/coresight/devices//regs/triginstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended input trigger signals. + What: /sys/bus/coresight/devices//regs/trigoutstatus Date: March 2020 KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of output trigger signals. +What: /sys/bus/coresight/devices//regs/trigoutstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended output trigger signals. + +What: /sys/bus/coresight/devices//regs/itctrl +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Control integration mode. + +What: /sys/bus/coresight/devices//regs/itchin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTCHIN inputs. + +What: /sys/bus/coresight/devices//regs/itchinack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTCHINACK input. + +What: /sys/bus/coresight/devices//regs/ittrigin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittrigin[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the values of the QCOM extended CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittriginack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/ittriginack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Write) Write the value of the QCOM extended CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/itchout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTCHOUT outputs. + +What: /sys/bus/coresight/devices//regs/itchoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTCHOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigout[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (RW) Read or write the value of the QCOM extended CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTTRIGOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigoutack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the value of the QCOM extended CTTRIGOUTACK input. + What: /sys/bus/coresight/devices//channels/trigin_attach Date: March 2020 KernelVersion: 5.7 From 5814373a857b08d03582726c4da8d2068a5897b5 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Thu, 21 May 2026 21:14:24 +0800 Subject: [PATCH 0062/1058] FROMLIST: stm: class: Add MIPI OST protocol support Add MIPI OST (Open System Trace) protocol support for stm to format the traces. The OST Protocol abstracts the underlying layers from the sending and receiving applications, thus removing dependencies on the connection media and platform implementation. OST over STP packet consists of Header/Payload/End. Header is designed to include the information required by all OST packets. Information that is not shared by all packets is left to the higher layer protocols. Thus, the OST Protocol Header can be regarded as the first part of a complete OST Packet Header, while a higher layer header can be regarded as an extension designed for a specific purpose. +--------+--------+--------+--------+ | start |version |entity |protocol| +--------+--------+--------+--------+ | stm version | magic | +-----------------------------------+ | cpu | +-----------------------------------+ | timestamp | | | +-----------------------------------+ | tgid | | | +-----------------------------------+ | payload | +-----------------------------------+ | ... | end | +-----------------------------------+ In header, there will be STARTSIMPLE/VERSION/ENTITY/PROTOCOL. STARTSIMPLE is used to signal the beginning of a simplified OST protocol. The Version field is a one byte, unsigned number identifying the version of the OST Protocol. The Entity ID field is a one byte unsigned number that identifies the source. Entity ID values (0~239) are defined and controlled by the TS owner, and shall be unique for the whole TS. The configfs entity attribute allows the user to configure which Entity ID is associated with each policy node. The Protocol ID field is a one byte unsigned number identifying the higher layer protocol of the OST Packet, i.e. identifying the format of the data after the OST Protocol Header. OST Control Protocol ID value represents the common control protocol, the remaining Protocol ID values may be used by any higher layer protocols capable of being transported by the OST Protocol. Link: https://lore.kernel.org/all/20260521-stm_p_ost-v6-1-e557900b686b@oss.qualcomm.com/ Co-developed-by: Tingwei Zhang Signed-off-by: Tingwei Zhang Co-developed-by: Yuanfang Zhang Signed-off-by: Yuanfang Zhang Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../ABI/testing/configfs-stp-policy-p_ost | 9 + Documentation/trace/index.rst | 1 + Documentation/trace/p_ost.rst | 39 +++ drivers/hwtracing/stm/Kconfig | 14 + drivers/hwtracing/stm/Makefile | 2 + drivers/hwtracing/stm/p_ost.c | 241 ++++++++++++++++++ 6 files changed, 306 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-stp-policy-p_ost create mode 100644 Documentation/trace/p_ost.rst create mode 100644 drivers/hwtracing/stm/p_ost.c diff --git a/Documentation/ABI/testing/configfs-stp-policy-p_ost b/Documentation/ABI/testing/configfs-stp-policy-p_ost new file mode 100644 index 0000000000000..8fb160b50c40b --- /dev/null +++ b/Documentation/ABI/testing/configfs-stp-policy-p_ost @@ -0,0 +1,9 @@ +What: /config/stp-policy/:p_ost.//entity +Date: May 2026 +KernelVersion: 7.1 +Description: + Set the entity ID which identifies the trace source in the + OST packet header. Entity ID values (0~239) are defined by + the TS owner. Currently supported values are ftrace, console + and diag. RW. + diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 5d9bf4694d5d0..9cd1e0b5af6da 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -72,6 +72,7 @@ interactions and system performance. intel_th stm sys-t + p_ost coresight/index rv/index hisi-ptt diff --git a/Documentation/trace/p_ost.rst b/Documentation/trace/p_ost.rst new file mode 100644 index 0000000000000..2b92e22296539 --- /dev/null +++ b/Documentation/trace/p_ost.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +MIPI OST over STP +=================== + +The OST (Open System Trace) driver is used with STM class devices to +generate standardized trace stream. Trace sources can be identified +by different entity IDs. + +CONFIG_STM_PROTO_OST is for p_ost driver enablement. Once this config +is enabled, you can select the p_ost protocol by command below: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy + +The policy name format is extended like this: + + :. + +With a coresight-stm device, it will look like "stm0:p_ost.policy". + +With the MIPI OST protocol driver, the attributes for each protocol node are: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +# ls /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +channels entity masters + +The entity here is the set of entities that p_ost supports. Currently +p_ost supports ftrace, console and diag entities. + +Set entity: +# echo 'ftrace' > /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity + +Get available and currently selected (shown in square brackets) entity: +# cat /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity +[ftrace] console diag + +See Documentation/ABI/testing/configfs-stp-policy-p_ost for more details. + diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig index cd7f0b0f3fbeb..4c83da5d95a05 100644 --- a/drivers/hwtracing/stm/Kconfig +++ b/drivers/hwtracing/stm/Kconfig @@ -40,6 +40,20 @@ config STM_PROTO_SYS_T If you don't know what this is, say N. +config STM_PROTO_OST + tristate "MIPI OST STM framing protocol driver" + default STM + help + This is an implementation of MIPI OST protocol to be used + over the STP transport. In addition to the data payload, it + also carries additional metadata for entity, better + means of trace source identification, etc. + + The receiving side must be able to decode this protocol in + addition to the MIPI STP, in order to extract the data. + + If you don't know what this is, say N. + config STM_DUMMY tristate "Dummy STM driver" help diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile index 1692fcd292779..d9c8615849b95 100644 --- a/drivers/hwtracing/stm/Makefile +++ b/drivers/hwtracing/stm/Makefile @@ -5,9 +5,11 @@ stm_core-y := core.o policy.o obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o +obj-$(CONFIG_STM_PROTO_OST) += stm_p_ost.o stm_p_basic-y := p_basic.o stm_p_sys-t-y := p_sys-t.o +stm_p_ost-y := p_ost.o obj-$(CONFIG_STM_DUMMY) += dummy_stm.o diff --git a/drivers/hwtracing/stm/p_ost.c b/drivers/hwtracing/stm/p_ost.c new file mode 100644 index 0000000000000..d2174872b7615 --- /dev/null +++ b/drivers/hwtracing/stm/p_ost.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * MIPI OST framing protocol for STM devices. + */ + +#include +#include +#include +#include +#include "stm.h" + +/* + * OST Base Protocol Header + * + * Position Bits Field Name + * 0 8 STARTSIMPLE + * 1 8 Version + * 2 8 Entity ID + * 3 8 Protocol ID + */ +#define OST_FIELD_STARTSIMPLE 0 +#define OST_FIELD_VERSION 8 +#define OST_FIELD_ENTITY 16 +#define OST_FIELD_PROTOCOL 24 + +#define OST_TOKEN_STARTSIMPLE 0x10 +#define OST_VERSION_MIPI1 0x10 + +/* entity id to identify the source */ +#define OST_ENTITY_FTRACE 0x01 +#define OST_ENTITY_CONSOLE 0x02 +#define OST_ENTITY_DIAG 0xEE + +#define OST_CONTROL_PROTOCOL 0x0 + +#define DATA_HEADER ((OST_TOKEN_STARTSIMPLE << OST_FIELD_STARTSIMPLE) | \ + (OST_VERSION_MIPI1 << OST_FIELD_VERSION) | \ + (OST_CONTROL_PROTOCOL << OST_FIELD_PROTOCOL)) + +#define STM_MAKE_VERSION(ma, mi) (((ma) << 8) | (mi)) +#define STM_HEADER_MAGIC (0x5953) + +enum ost_entity_type { + OST_ENTITY_TYPE_NONE, + OST_ENTITY_TYPE_FTRACE, + OST_ENTITY_TYPE_CONSOLE, + OST_ENTITY_TYPE_DIAG, +}; + +static const char * const str_ost_entity_type[] = { + [OST_ENTITY_TYPE_NONE] = "none", + [OST_ENTITY_TYPE_FTRACE] = "ftrace", + [OST_ENTITY_TYPE_CONSOLE] = "console", + [OST_ENTITY_TYPE_DIAG] = "diag", +}; + +static const u32 ost_entity_value[] = { + [OST_ENTITY_TYPE_NONE] = 0, + [OST_ENTITY_TYPE_FTRACE] = OST_ENTITY_FTRACE, + [OST_ENTITY_TYPE_CONSOLE] = OST_ENTITY_CONSOLE, + [OST_ENTITY_TYPE_DIAG] = OST_ENTITY_DIAG, +}; + +struct ost_policy_node { + enum ost_entity_type entity_type; +}; + +struct ost_output { + struct ost_policy_node node; +}; + +/* Set default entity type as none */ +static void ost_policy_node_init(void *priv) +{ + struct ost_policy_node *pn = priv; + + pn->entity_type = OST_ENTITY_TYPE_NONE; +} + +static int ost_output_open(void *priv, struct stm_output *output) +{ + struct ost_policy_node *pn = priv; + struct ost_output *opriv; + + opriv = kzalloc_obj(*opriv, GFP_ATOMIC); + if (!opriv) + return -ENOMEM; + + memcpy(&opriv->node, pn, sizeof(opriv->node)); + output->pdrv_private = opriv; + return 0; +} + +static void ost_output_close(struct stm_output *output) +{ + kfree(output->pdrv_private); +} + +static ssize_t ost_t_policy_entity_show(struct config_item *item, + char *page) +{ + struct ost_policy_node *pn = to_pdrv_policy_node(item); + ssize_t sz = 0; + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (i == pn->entity_type) + sz += sysfs_emit_at(page, sz, "[%s] ", str_ost_entity_type[i]); + else + sz += sysfs_emit_at(page, sz, "%s ", str_ost_entity_type[i]); + } + + sz += sysfs_emit_at(page, sz, "\n"); + return sz; +} + +static int entity_index(const char *str) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (sysfs_streq(str, str_ost_entity_type[i])) + return i; + } + + return 0; +} + +static ssize_t +ost_t_policy_entity_store(struct config_item *item, const char *page, + size_t count) +{ + struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex; + struct ost_policy_node *pn = to_pdrv_policy_node(item); + int i; + + i = entity_index(page); + if (i) { + mutex_lock(mutexp); + pn->entity_type = i; + mutex_unlock(mutexp); + } else { + return -EINVAL; + } + + return count; +} +CONFIGFS_ATTR(ost_t_policy_, entity); + +static struct configfs_attribute *ost_t_policy_attrs[] = { + &ost_t_policy_attr_entity, + NULL, +}; + +static ssize_t +notrace ost_write(struct stm_data *data, struct stm_output *output, + unsigned int chan, const char *buf, size_t count, + struct stm_source_data *source) +{ + struct ost_output *op = output->pdrv_private; + unsigned int c = output->channel + chan; + unsigned int m = output->master; + const unsigned char nil = 0; + u32 header = DATA_HEADER; + struct trc_hdr { + u16 version; + u16 magic; + u32 cpu; + u64 timestamp; + u64 tgid; + } hdr; + ssize_t sz; + + /* + * Identify the source by entity type. + * If entity type is not set, return error value. + */ + if (op->node.entity_type) + header |= (ost_entity_value[op->node.entity_type] << OST_FIELD_ENTITY); + else + return -EINVAL; + + /* + * STP framing rules for OST frames: + * * the first packet of the OST frame is marked; + * * the last packet is a FLAG with timestamped tag. + */ + /* Message layout: HEADER / DATA / TAIL */ + /* HEADER */ + sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_MARKED, + 4, (u8 *)&header); + if (sz <= 0) + return sz; + + /* DATA */ + hdr.version = STM_MAKE_VERSION(0, 3); + hdr.magic = STM_HEADER_MAGIC; + hdr.cpu = raw_smp_processor_id(); + hdr.timestamp = sched_clock(); + hdr.tgid = task_tgid_nr(current); + sz = stm_data_write(data, m, c, false, &hdr, sizeof(hdr)); + if (sz <= 0) + return sz; + + sz = stm_data_write(data, m, c, false, buf, count); + + /* TAIL */ + if (sz > 0) + data->packet(data, m, c, STP_PACKET_FLAG, + STP_PACKET_TIMESTAMPED, 0, &nil); + + return sz; +} + +static const struct stm_protocol_driver ost_pdrv = { + .owner = THIS_MODULE, + .name = "p_ost", + .priv_sz = sizeof(struct ost_policy_node), + .write = ost_write, + .policy_attr = ost_t_policy_attrs, + .output_open = ost_output_open, + .output_close = ost_output_close, + .policy_node_init = ost_policy_node_init, +}; + +static int ost_stm_init(void) +{ + return stm_register_protocol(&ost_pdrv); +} +module_init(ost_stm_init); + +static void ost_stm_exit(void) +{ + stm_unregister_protocol(&ost_pdrv); +} +module_exit(ost_stm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver"); From ff0042838e8b1f6b963d910c51180cb7902788a6 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:41 -0800 Subject: [PATCH 0063/1058] FROMLIST: dt-bindings: arm: coresight: Add 'qcom,cpu-bound-components' property Introduce the `qcom,cpu-bound-components` boolean property for CoreSight components (TMC, Funnel, and Replicator). This property indicates that the component is physically located within a CPU cluster power domain. Such components share the power state of the cluster and may require special handling (e.g., cross-CPU register access) compared to system-wide components. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-1-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../bindings/arm/arm,coresight-dynamic-funnel.yaml | 5 +++++ .../bindings/arm/arm,coresight-dynamic-replicator.yaml | 5 +++++ Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml index b0693cd46d27a..8756ecce4d11a 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml @@ -57,6 +57,11 @@ properties: power-domains: maxItems: 1 + qcom,cpu-bound-components: + type: boolean + description: + Indicates whether the funnel is located physically within cpu cluster. + label: description: Description of a coresight device. diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml index 17ea936b796fd..2c6e78f02ed84 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml @@ -67,6 +67,11 @@ properties: Indicates that the replicator will lose register context when AMBA clock is removed which is observed in some replicator designs. + qcom,cpu-bound-components: + type: boolean + description: + Indicates whether the replicator is located physically within cpu cluster. + in-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml index 9dc096698c657..046ad8639e21b 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml @@ -86,6 +86,11 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 maximum: 15 + qcom,cpu-bound-components: + type: boolean + description: + indicates whether the TMC-ETF is located physically within cpu cluster. + in-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false From d741818c85aba7c98944c217c49e33b76bccaa68 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:42 -0800 Subject: [PATCH 0064/1058] FROMLIST: coresight-funnel: Support CPU cluster funnel initialization Funnels associated with CPU clusters reside in the cluster's power domain. Unlike dynamic funnels (which are typically system-wide), these per-cluster funnels are only accessible when the cluster is powered on. Standard runtime PM may not suffice to wake up a cluster from low-power states, making direct register access unreliable. Enhance the funnel driver to support these per-cluster devices: 1. Safe Initialization: - Identify CPU cluster funnels via "qcom,cpu-bound-components". - Use smp_call_function_single() to perform hardware initialization (claim tag clearing) on a CPU within the cluster. - Refactor the probe flow to encapsulate device registration in funnel_add_coresight_dev(). 2. Cross-CPU Enablement: - Update funnel_enable() to use smp_call_function_single() when enabling the hardware on a cluster-bound funnel. 3. Debug Interface Support: - Update funnel_ctrl_show() to safely read the control register via cross-CPU calls when necessary. This ensures that funnel operations remain safe and functional even when the associated CPU cluster is in aggressive low-power states. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-2-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-funnel.c | 183 +++++++++++++++--- 1 file changed, 152 insertions(+), 31 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 0abc11f0690c5..fc4286caa38dc 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ * @csdev: component vitals needed by the framework. * @priority: port selection order. * @spinlock: serialize enable/disable operations. + * @supported_cpus: Represent the CPUs related to this funnel. */ struct funnel_drvdata { void __iomem *base; @@ -46,6 +48,13 @@ struct funnel_drvdata { struct coresight_device *csdev; unsigned long priority; raw_spinlock_t spinlock; + struct cpumask *supported_cpus; +}; + +struct funnel_smp_arg { + struct funnel_drvdata *drvdata; + int port; + int rc; }; static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) @@ -74,6 +83,33 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) return rc; } +static void funnel_enable_hw_smp_call(void *info) +{ + struct funnel_smp_arg *arg = info; + + arg->rc = dynamic_funnel_enable_hw(arg->drvdata, arg->port); +} + +static int funnel_enable_hw(struct funnel_drvdata *drvdata, int port) +{ + int cpu, ret; + struct funnel_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return dynamic_funnel_enable_hw(drvdata, port); + + arg.drvdata = drvdata; + arg.port = port; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + funnel_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static int funnel_enable(struct coresight_device *csdev, struct coresight_connection *in, struct coresight_connection *out) @@ -84,19 +120,24 @@ static int funnel_enable(struct coresight_device *csdev, bool first_enable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (in->dest_refcnt == 0) { - if (drvdata->base) - rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); - if (!rc) - first_enable = true; - } - if (!rc) + + if (in->dest_refcnt == 0) + first_enable = true; + else in->dest_refcnt++; + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", - in->dest_port); + if (first_enable) { + if (drvdata->base) + rc = funnel_enable_hw(drvdata, in->dest_port); + if (!rc) { + in->dest_refcnt++; + dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", + in->dest_port); + } + } + return rc; } @@ -186,15 +227,39 @@ static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata) return functl; } +static void get_funnel_ctrl_smp_call(void *info) +{ + struct funnel_smp_arg *arg = info; + + arg->rc = get_funnel_ctrl_hw(arg->drvdata); +} + static ssize_t funnel_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf) { u32 val; + int cpu, ret; struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct funnel_smp_arg arg = { 0 }; pm_runtime_get_sync(dev->parent); - - val = get_funnel_ctrl_hw(drvdata); + if (!drvdata->supported_cpus) { + val = get_funnel_ctrl_hw(drvdata); + } else { + arg.drvdata = drvdata; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + get_funnel_ctrl_smp_call, &arg, 1); + if (!ret) + break; + } + if (!ret) { + val = arg.rc; + } else { + pm_runtime_put(dev->parent); + return ret; + } + } pm_runtime_put(dev->parent); @@ -209,22 +274,68 @@ static struct attribute *coresight_funnel_attrs[] = { }; ATTRIBUTE_GROUPS(coresight_funnel); +static void funnel_clear_self_claim_tag(struct funnel_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static void funnel_init_on_cpu(void *info) +{ + struct funnel_drvdata *drvdata = info; + + funnel_clear_self_claim_tag(drvdata); +} + +static int funnel_add_coresight_dev(struct device *dev) +{ + struct coresight_desc desc = { 0 }; + struct funnel_drvdata *drvdata = dev_get_drvdata(dev); + + if (drvdata->base) { + desc.groups = coresight_funnel_groups; + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); + } + + desc.name = coresight_alloc_device_name("funnel", dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_LINK; + desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; + desc.ops = &funnel_cs_ops; + desc.pdata = dev->platform_data; + desc.dev = dev; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + return 0; +} + +static struct cpumask *funnel_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + static int funnel_probe(struct device *dev, struct resource *res) { void __iomem *base; struct coresight_platform_data *pdata = NULL; struct funnel_drvdata *drvdata; - struct coresight_desc desc = { 0 }; - int ret; + int cpu, ret; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-funnel")) dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n"); - desc.name = coresight_alloc_device_name("funnel", dev); - if (!desc.name) - return -ENOMEM; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -242,9 +353,6 @@ static int funnel_probe(struct device *dev, struct resource *res) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base; - desc.groups = coresight_funnel_groups; - desc.access = CSDEV_ACCESS_IOMEM(base); - coresight_clear_self_claim_tag(&desc.access); } dev_set_drvdata(dev, drvdata); @@ -256,23 +364,36 @@ static int funnel_probe(struct device *dev, struct resource *res) dev->platform_data = pdata; raw_spin_lock_init(&drvdata->spinlock); - desc.type = CORESIGHT_DEV_TYPE_LINK; - desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; - desc.ops = &funnel_cs_ops; - desc.pdata = pdata; - desc.dev = dev; - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) - return PTR_ERR(drvdata->csdev); - return 0; + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = funnel_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + funnel_init_on_cpu, drvdata, 1); + if (!ret) + break; + } + cpus_read_unlock(); + + if (ret) + return 0; + } else if (res) { + funnel_clear_self_claim_tag(drvdata); + } + + return funnel_add_coresight_dev(dev); } static int funnel_remove(struct device *dev) { struct funnel_drvdata *drvdata = dev_get_drvdata(dev); - coresight_unregister(drvdata->csdev); + if (drvdata->csdev) + coresight_unregister(drvdata->csdev); return 0; } From df4b0f71b599937e9d22c3826eb2fbfae7df3126 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:43 -0800 Subject: [PATCH 0065/1058] FROMLIST: coresight-funnel: Defer probe when associated CPUs are offline Per-cluster funnels rely on the associated CPU cluster being online to securely access registers during initialization. If all CPUs in the cluster are offline during probe, these operations fail. Support deferred initialization for these devices: 1. Track funnels that fail to probe due to offline CPUs in a global list. 2. Register a CPU hotplug notifier (funnel_online_cpu) to detect when a relevant CPU comes online. 3. Upon CPU online, retry the hardware initialization and registration with the CoreSight framework. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-3-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-funnel.c | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index fc4286caa38dc..8cfebe4cbd216 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -31,6 +31,10 @@ #define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT) #define FUNNEL_ENSx_MASK 0xff +static LIST_HEAD(funnel_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + /** * struct funnel_drvdata - specifics associated to a funnel component * @base: memory mapped base address for this component. @@ -40,6 +44,8 @@ * @priority: port selection order. * @spinlock: serialize enable/disable operations. * @supported_cpus: Represent the CPUs related to this funnel. + * @dev: pointer to the device associated with this funnel. + * @link: list node for adding this funnel to the delayed probe list. */ struct funnel_drvdata { void __iomem *base; @@ -49,6 +55,8 @@ struct funnel_drvdata { unsigned long priority; raw_spinlock_t spinlock; struct cpumask *supported_cpus; + struct device *dev; + struct list_head link; }; struct funnel_smp_arg { @@ -369,7 +377,7 @@ static int funnel_probe(struct device *dev, struct resource *res) drvdata->supported_cpus = funnel_get_supported_cpus(dev); if (!drvdata->supported_cpus) return -EINVAL; - + drvdata->dev = dev; cpus_read_lock(); for_each_cpu(cpu, drvdata->supported_cpus) { ret = smp_call_function_single(cpu, @@ -377,10 +385,15 @@ static int funnel_probe(struct device *dev, struct resource *res) if (!ret) break; } - cpus_read_unlock(); - if (ret) + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &funnel_delay_probe); + cpus_read_unlock(); return 0; + } + + cpus_read_unlock(); } else if (res) { funnel_clear_self_claim_tag(drvdata); } @@ -392,9 +405,12 @@ static int funnel_remove(struct device *dev) { struct funnel_drvdata *drvdata = dev_get_drvdata(dev); - if (drvdata->csdev) + if (drvdata->csdev) { coresight_unregister(drvdata->csdev); - + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } return 0; } @@ -531,14 +547,51 @@ static struct amba_driver dynamic_funnel_driver = { .id_table = dynamic_funnel_ids, }; +static int funnel_online_cpu(unsigned int cpu) +{ + struct funnel_drvdata *drvdata, *tmp; + int ret; + + list_for_each_entry_safe(drvdata, tmp, &funnel_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + funnel_clear_self_claim_tag(drvdata); + funnel_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + } + } + return 0; +} + static int __init funnel_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-funnel:online", + funnel_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver); } static void __exit funnel_exit(void) { coresight_remove_driver(&dynamic_funnel_driver, &funnel_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(funnel_init); From fa6396d7f6d6e2a35f1e1d39b800f37fd54ea312 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:44 -0800 Subject: [PATCH 0066/1058] FROMLIST: coresight-replicator: Support CPU cluster replicator initialization Replicators associated with CPU clusters reside in the cluster's power domain. Unlike system-wide replicators, their registers are only accessible when the cluster is powered on. Standard runtime PM may not suffice to wake up a cluster from low-power states, making direct register access unreliable during initialization or operation. Enhance the replicator driver to support these per-cluster devices: 1. Safe Initialization: - Identify per-cluster replicators via device properties. - Use smp_call_function_single() to perform hardware initialization (reset and claim tag clearing) on a CPU within the cluster. - Refactor the probe flow to encapsulate device registration in replicator_add_coresight_dev(). 2. Cross-CPU Enablement: - Update replicator_enable() to use smp_call_function_single() when enabling the hardware on a cluster-bound replicator. 3. Claim/Disclaim Handling: - Introduce replicator_claim/disclaim_device_unlocked() to manage device access safely before full framework registration. This ensures that replicator operations remain robust even when the associated CPU cluster is in low-power states, while maintaining compatibility with existing system-level replicators. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-4-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../coresight/coresight-replicator.c | 200 +++++++++++++++--- 1 file changed, 167 insertions(+), 33 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 2f382de357ee4..c8d2a6082a97f 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ * @csdev: component vitals needed by the framework * @spinlock: serialize enable/disable operations. * @check_idfilter_val: check if the context is lost upon clock removal. + * @supported_cpus: Represent the CPUs related to this funnel. */ struct replicator_drvdata { void __iomem *base; @@ -41,18 +43,61 @@ struct replicator_drvdata { struct coresight_device *csdev; raw_spinlock_t spinlock; bool check_idfilter_val; + struct cpumask *supported_cpus; }; -static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) +struct replicator_smp_arg { + struct replicator_drvdata *drvdata; + int outport; + int rc; +}; + +static void replicator_clear_self_claim_tag(struct replicator_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static int replicator_claim_device_unlocked(struct replicator_drvdata *drvdata) +{ + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + u32 claim_tag; + + if (csdev) + return coresight_claim_device_unlocked(csdev); + + writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, drvdata->base + CORESIGHT_CLAIMSET); + + claim_tag = readl_relaxed(drvdata->base + CORESIGHT_CLAIMCLR); + if (claim_tag != CORESIGHT_CLAIM_SELF_HOSTED) { + coresight_clear_self_claim_tag_unlocked(&access); + return -EBUSY; + } + + return 0; +} + +static void replicator_disclaim_device_unlocked(struct replicator_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + if (csdev) + return coresight_disclaim_device_unlocked(csdev); + coresight_clear_self_claim_tag_unlocked(&access); +} + +static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) +{ CS_UNLOCK(drvdata->base); - if (!coresight_claim_device_unlocked(csdev)) { + if (!replicator_claim_device_unlocked(drvdata)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); - coresight_disclaim_device_unlocked(csdev); + replicator_disclaim_device_unlocked(drvdata); } CS_LOCK(drvdata->base); @@ -114,6 +159,34 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, return rc; } +static void replicator_enable_hw_smp_call(void *info) +{ + struct replicator_smp_arg *arg = info; + + arg->rc = dynamic_replicator_enable(arg->drvdata, 0, arg->outport); +} + +static int replicator_enable_hw(struct replicator_drvdata *drvdata, + int inport, int outport) +{ + int cpu, ret; + struct replicator_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return dynamic_replicator_enable(drvdata, 0, outport); + + arg.drvdata = drvdata; + arg.outport = outport; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, replicator_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + + return ret; +} + static int replicator_enable(struct coresight_device *csdev, struct coresight_connection *in, struct coresight_connection *out) @@ -124,19 +197,24 @@ static int replicator_enable(struct coresight_device *csdev, bool first_enable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (out->src_refcnt == 0) { - if (drvdata->base) - rc = dynamic_replicator_enable(drvdata, in->dest_port, - out->src_port); - if (!rc) - first_enable = true; - } - if (!rc) + + if (out->src_refcnt == 0) + first_enable = true; + else out->src_refcnt++; raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "REPLICATOR enabled\n"); + if (first_enable) { + if (drvdata->base) + rc = replicator_enable_hw(drvdata, in->dest_port, + out->src_port); + if (!rc) { + out->src_refcnt++; + dev_dbg(&csdev->dev, "REPLICATOR enabled\n"); + return rc; + } + } + return rc; } @@ -215,23 +293,69 @@ static const struct attribute_group *replicator_groups[] = { NULL, }; +static int replicator_add_coresight_dev(struct device *dev) +{ + struct coresight_desc desc = { 0 }; + struct replicator_drvdata *drvdata = dev_get_drvdata(dev); + + if (drvdata->base) { + desc.groups = replicator_groups; + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); + } + + desc.name = coresight_alloc_device_name("replicator", dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_LINK; + desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; + desc.ops = &replicator_cs_ops; + desc.pdata = dev->platform_data; + desc.dev = dev; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + + return 0; +} + +static void replicator_init_hw(struct replicator_drvdata *drvdata) +{ + replicator_clear_self_claim_tag(drvdata); + replicator_reset(drvdata); +} + +static void replicator_init_on_cpu(void *info) +{ + struct replicator_drvdata *drvdata = info; + + replicator_init_hw(drvdata); +} + +static struct cpumask *replicator_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + static int replicator_probe(struct device *dev, struct resource *res) { struct coresight_platform_data *pdata = NULL; struct replicator_drvdata *drvdata; - struct coresight_desc desc = { 0 }; void __iomem *base; - int ret; + int cpu, ret; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-replicator")) dev_warn_once(dev, "Uses OBSOLETE CoreSight replicator binding\n"); - desc.name = coresight_alloc_device_name("replicator", dev); - if (!desc.name) - return -ENOMEM; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -249,9 +373,6 @@ static int replicator_probe(struct device *dev, struct resource *res) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base; - desc.groups = replicator_groups; - desc.access = CSDEV_ACCESS_IOMEM(base); - coresight_clear_self_claim_tag(&desc.access); } if (fwnode_property_present(dev_fwnode(dev), @@ -266,25 +387,38 @@ static int replicator_probe(struct device *dev, struct resource *res) dev->platform_data = pdata; raw_spin_lock_init(&drvdata->spinlock); - desc.type = CORESIGHT_DEV_TYPE_LINK; - desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; - desc.ops = &replicator_cs_ops; - desc.pdata = dev->platform_data; - desc.dev = dev; - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) - return PTR_ERR(drvdata->csdev); + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = replicator_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + replicator_init_on_cpu, drvdata, 1); + if (!ret) + break; + } + cpus_read_unlock(); - replicator_reset(drvdata); - return 0; + if (ret) + return 0; + } else if (res) { + replicator_init_hw(drvdata); + } + + ret = replicator_add_coresight_dev(dev); + + return ret; } static int replicator_remove(struct device *dev) { struct replicator_drvdata *drvdata = dev_get_drvdata(dev); - coresight_unregister(drvdata->csdev); + if (drvdata->csdev) + coresight_unregister(drvdata->csdev); return 0; } From 20583f92a7796f54cc81a32192052b4440cd0c3c Mon Sep 17 00:00:00 2001 From: Ronak Raheja Date: Sun, 29 Mar 2026 23:22:47 +0530 Subject: [PATCH 0067/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add USB support for Kaanapali SoC Add the base USB devicetree definitions for Kaanapali platform. The overall chipset contains a single DWC3 USB3 controller (rev. 200a), SS QMP PHY (rev. v8) and M31 eUSB2 PHY. Signed-off-by: Ronak Raheja Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/all/20260329175249.2946508-2-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 154 ++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 7aa9653bd456e..c3ba00eaa8c63 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -6112,6 +6112,160 @@ reg = <0x100 0x80>; }; }; + + usb_hsphy: phy@88e3000 { + compatible = "qcom,kaanapali-m31-eusb2-phy", + "qcom,sm8750-m31-eusb2-phy"; + reg = <0x0 0x88e3000 0x0 0x29c>; + + clocks = <&tcsr TCSR_USB2_CLKREF_EN>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_dp_qmpphy: phy@88e8000 { + compatible = "qcom,kaanapali-qmp-usb3-dp-phy", + "qcom,sm8750-qmp-usb3-dp-phy"; + reg = <0x0 0x088e8000 0x0 0x4000>; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&tcsr TCSR_USB3_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "usb3_pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", + "common"; + + power-domains = <&gcc GCC_USB3_PHY_GDSC>; + + #clock-cells = <1>; + #phy-cells = <1>; + + orientation-switch; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dp_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dp_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_dwc3_ss>; + }; + }; + + port@2 { + reg = <2>; + + usb_dp_qmpphy_dp_in: endpoint { + }; + }; + }; + }; + + usb: usb@a600000 { + compatible = "qcom,kaanapali-dwc3", "qcom,snps-dwc3"; + reg = <0x0 0x0a600000 0x0 0xfc100>; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 14 IRQ_TYPE_EDGE_BOTH>, + <&pdc 15 IRQ_TYPE_EDGE_BOTH>, + <&pdc 17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + power-domains = <&gcc GCC_USB30_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + interconnects = <&aggre_noc MASTER_USB3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_USB3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "usb-ddr", "apps-usb"; + iommus = <&apps_smmu 0x40 0x0>; + + phys = <&usb_hsphy>, <&usb_dp_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + + snps,hird-threshold = /bits/ 8 <0x0>; + snps,usb2-gadget-lpm-disable; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,is-utmi-l1-suspend; + snps,usb3_lpm_capable; + snps,usb2-lpm-disable; + snps,has-lpm-erratum; + tx-fifo-resize; + dma-coherent; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dwc3_ss: endpoint { + remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; + }; + }; + }; + }; }; thermal-zones { From 79e86756aaf15fbe5b9550d61347ecbe4fbec451 Mon Sep 17 00:00:00 2001 From: Ronak Raheja Date: Sun, 29 Mar 2026 23:22:48 +0530 Subject: [PATCH 0068/1058] FROMLIST: arm64: dts: qcom: kaanpaali: Add USB support for MTP platform Enable USB support on Kaanapali MTP variant. Enable USB controller in device mode till glink node is added. Signed-off-by: Ronak Raheja Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/all/20260329175249.2946508-3-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index f9b5b5718b904..9e273a75d582d 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -82,6 +82,11 @@ }; }; + pmih0108_e1_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; + }; + sound { compatible = "qcom,kaanapali-sndcard", "qcom,sm8450-sndcard"; model = "Kaanapali-MTP"; From d01500a543546f1786f0d9b63ecdb235bc570977 Mon Sep 17 00:00:00 2001 From: Ronak Raheja Date: Sun, 29 Mar 2026 23:22:49 +0530 Subject: [PATCH 0069/1058] FROMLIST: arm64: dts: qcom: kaanpaali: Add USB support for QRD platform Enable USB support on Kaanapali QRD variant. Enable USB controller in device mode till glink node is added. Signed-off-by: Ronak Raheja Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/all/20260329175249.2946508-4-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index 55d02219ef4e9..28202a8439413 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -80,6 +80,11 @@ wakeup-source; }; }; + + pmih0108_e1_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; + }; }; &apps_rsc { From 48dc294fe6f22308b579832bcf523a9848f44fef Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Wed, 20 May 2026 14:16:19 +0800 Subject: [PATCH 0070/1058] FROMLIST: arm64: dts: qcom: kaanapali: add the GPU SMMU node Add the Adreno GPU SMMU node for kaanapali platform. Link: https://lore.kernel.org/r/20260512-kaana-gpu-dt-v1-3-13e1c07c2050@oss.qualcomm.com Signed-off-by: Qingqing Zhou Signed-off-by: Akhil P Oommen Signed-off-by: Yijie Yang --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index c3ba00eaa8c63..2d5a8ff528534 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -2601,6 +2601,47 @@ #power-domain-cells = <1>; }; + adreno_smmu: iommu@3da0000 { + compatible = "qcom,kaanapali-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x3da0000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + dma-coherent; + + power-domains = <&gpucc GPU_CC_CX_GDSC>; + + clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>; + clock-names = "hlos"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + remoteproc_adsp: remoteproc@6800000 { compatible = "qcom,kaanapali-adsp-pas", "qcom,sm8550-adsp-pas"; reg = <0x0 0x06800000 0x0 0x10000>; From b919425bec4faca386ad52fec3f6129edddb5307 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Wed, 20 May 2026 14:16:19 +0800 Subject: [PATCH 0071/1058] FROMLIST: arm64: dts: qcom: Add GPU support for Kaanapali Adreno 840 present in Kaanapali SoC is the second generation GPU in A8x family. It is based on the new slice architecture with 3 slices, higher GMEM/caches etc. There is some re-arrangement in the reglist to properly cover maximum register region. Other than this, the DT description is mostly similar to the existing chipsets except the OPP tables. Link: https://lore.kernel.org/r/20260512-kaana-gpu-dt-v1-5-13e1c07c2050@oss.qualcomm.com Signed-off-by: Akhil P Oommen Reviewed-by: Dmitry Baryshkov Signed-off-by: Yijie Yang --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 232 ++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 2d5a8ff528534..1f0a653444bba 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -2577,6 +2577,238 @@ #power-domain-cells = <1>; }; + gpu: gpu@3d00000 { + compatible = "qcom,adreno-44050a01", "qcom,adreno"; + reg = <0x0 0x03d00000 0x0 0x6c000>, + <0x0 0x03d9e000 0x0 0x2000>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem"; + + interrupts = ; + + iommus = <&adreno_smmu 0 0x0>, + <&adreno_smmu 1 0x0>; + + operating-points-v2 = <&gpu_opp_table>; + + qcom,gmu = <&gmu>; + #cooling-cells = <2>; + + nvmem-cells = <&gpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + + interconnects = <&gem_noc MASTER_GFX3D QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "gfx-mem"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_microcode_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2-adreno", + "operating-points-v2"; + + opp-222000000 { + opp-hz = /bits/ 64 <222000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + /* ACD is disabled */ + }; + + opp-282000000 { + opp-hz = /bits/ 64 <282000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xca2e5ffd>; + }; + + opp-342000000 { + opp-hz = /bits/ 64 <342000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe22a5ffd>; + }; + + opp-382000000 { + opp-hz = /bits/ 64 <382000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa22c5ffd>; + }; + + opp-422000000 { + opp-hz = /bits/ 64 <422000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa22c5ffd>; + }; + + opp-461000000 { + opp-hz = /bits/ 64 <461000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82e5ffd>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82c5ffd>; + }; + + opp-539000000 { + opp-hz = /bits/ 64 <539000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc82b5ffd>; + }; + + opp-578000000 { + opp-hz = /bits/ 64 <578000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-646000000 { + opp-hz = /bits/ 64 <646000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-726000000 { + opp-hz = /bits/ 64 <726000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882f5ffd>; + }; + + opp-826000000 { + opp-hz = /bits/ 64 <826000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-902000000 { + opp-hz = /bits/ 64 <902000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-967000000 { + opp-hz = /bits/ 64 <967000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882a5ffd>; + }; + + opp-1050000000 { + opp-hz = /bits/ 64 <1050000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x88295ffd>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa02e5ffd>; + }; + + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x03>; + qcom,opp-acd-level = <0x802d5ffd>; + }; + }; + }; + + gmu: gmu@3d6c000 { + compatible = "qcom,adreno-gmu-840.1", "qcom,adreno-gmu"; + + reg = <0x0 0x03d6c000 0x0 0x68000>; + reg-names = "gmu"; + + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + + clocks = <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gcc GCC_GPU_GEMNOC_GFX_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>; + clock-names = "ahb", + "gmu", + "cxo", + "memnoc", + "hub"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gxclkctl GX_CLKCTL_GX_GDSC>; + power-domain-names = "cx", + "gx"; + + iommus = <&adreno_smmu 5 0x0>; + + qcom,qmp = <&aoss_qmp>; + + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-475000000 { + opp-hz = /bits/ 64 <475000000>; + opp-level = ; + }; + + opp-575000000 { + opp-hz = /bits/ 64 <575000000>; + opp-level = ; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-level = ; + }; + + opp-725000000 { + opp-hz = /bits/ 64 <725000000>; + opp-level = ; + }; + + opp-750000000 { + opp-hz = /bits/ 64 <750000000>; + opp-level = ; + }; + }; + }; + gxclkctl: clock-controller@3d64000 { compatible = "qcom,kaanapali-gxclkctl"; reg = <0x0 0x03d64000 0x0 0x6000>; From 8b93a0633dcd6b3e30f1bf950030cc1ecc511845 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Wed, 20 May 2026 14:16:20 +0800 Subject: [PATCH 0072/1058] FROMLIST: arm64: dts: qcom: kaanapali-mtp: Enable GPU Add the secure firmware name property and enable GPU support on Kaanapali MTP device. Link: https://lore.kernel.org/r/20260512-kaana-gpu-dt-v1-7-13e1c07c2050@oss.qualcomm.com Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Yijie Yang --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 9e273a75d582d..f9a3494114d44 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -870,6 +870,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/kaanapali/gen80200_zap.mbn"; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; From 6b07da46760d531df4be21c15cd6c3d2774a7b3a Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Wed, 20 May 2026 14:16:21 +0800 Subject: [PATCH 0073/1058] FROMLIST: arm64: dts: qcom: kaanapali-qrd: Enable GPU Add the secure firmware name property and enable GPU support on Kaanapali QRD device. Link: https://lore.kernel.org/r/20260512-kaana-gpu-dt-v1-8-13e1c07c2050@oss.qualcomm.com Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Yijie Yang --- arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index 28202a8439413..e20cf30d3dea4 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -698,6 +698,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/kaanapali/gen80200_zap.mbn"; +}; + &pmh0101_flash { status = "okay"; From d09ac25a606eba04a497cf6741e68f2c6059ffe5 Mon Sep 17 00:00:00 2001 From: Dipa Mantre Date: Wed, 15 Apr 2026 16:27:08 +0530 Subject: [PATCH 0074/1058] FROMLIST: arm64: dts: qcom: kaanapali: Enable cpufreq cooling devices Add cooling-cells property to the CPU nodes to support cpufreq cooling devices. Signed-off-by: Dipa Mantre Reviewed-by: Gaurav Kohli Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260415-cpufreq_kaanapali-v1-1-1fa94105d5c2@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 1f0a653444bba..c4fc21349d859 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -48,6 +48,7 @@ power-domains = <&cpu_pd0>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; l2_0: l2-cache { compatible = "cache"; @@ -65,6 +66,7 @@ power-domains = <&cpu_pd1>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu2: cpu@200 { @@ -76,6 +78,7 @@ power-domains = <&cpu_pd2>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu3: cpu@300 { @@ -87,6 +90,7 @@ power-domains = <&cpu_pd3>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu4: cpu@400 { @@ -98,6 +102,7 @@ power-domains = <&cpu_pd4>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu5: cpu@500 { @@ -109,6 +114,7 @@ power-domains = <&cpu_pd5>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu6: cpu@10000 { @@ -120,6 +126,7 @@ power-domains = <&cpu_pd6>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 1>; + #cooling-cells = <2>; l2_1: l2-cache { compatible = "cache"; @@ -137,6 +144,7 @@ power-domains = <&cpu_pd7>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 1>; + #cooling-cells = <2>; }; cpu-map { From a1c6e1f379fc8738ae3824e4e0e58a130a1d91f0 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Tue, 12 May 2026 03:53:18 +0530 Subject: [PATCH 0075/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add qfprom node Add the qfprom node and gpu related subnodes on Kaanapali SoC. Link: https://lore.kernel.org/all/20260512-kaana-gpu-dt-v1-4-13e1c07c2050@oss.qualcomm.com/ Signed-off-by: Jingyi Wang Signed-off-by: Akhil P Oommen Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Shivam Rawat --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index c4fc21349d859..cb93ffa3effd2 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -6112,6 +6112,18 @@ }; }; + efuse@221c8000 { + compatible = "qcom,kaanapali-qfprom", "qcom,qfprom"; + reg = <0x0 0x221c8000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + gpu_speed_bin: gpu-speed-bin@142 { + reg = <0x142 0x2>; + bits = <3 9>; + }; + }; + nsp_noc: interconnect@260c0000 { compatible = "qcom,kaanapali-nsp-noc"; reg = <0x0 0x260c0000 0x0 0x21280>; From 437234fd83ab54a2c5d7611fa0f19791cb21936d Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Tue, 12 May 2026 03:53:20 +0530 Subject: [PATCH 0076/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add GPU cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the GPU does not throttle its speed automatically when it reaches high temperatures. Set up GPU cooling by throttling the GPU speed when reaching 105°C. Link: https://lore.kernel.org/all/20260512-kaana-gpu-dt-v1-6-13e1c07c2050@oss.qualcomm.com/ Signed-off-by: Gaurav Kohli Signed-off-by: Akhil P Oommen Signed-off-by: Shivam Rawat --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 165 +++++++++++++++++++----- 1 file changed, 135 insertions(+), 30 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index cb93ffa3effd2..714cb21a47c81 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -26,6 +26,7 @@ #include #include #include +#include #include "kaanapali-ipcc.h" @@ -7211,13 +7212,15 @@ }; gpuss-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 0>; trips { - gpuss-0-hot { - temperature = <120000>; + gpuss_0_alert0: gpuss-0-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-0-critical { @@ -7226,16 +7229,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_0_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 1>; trips { - gpuss-1-hot { - temperature = <120000>; + gpuss_1_alert0: gpuss-1-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-1-critical { @@ -7244,16 +7256,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_1_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 2>; trips { - gpuss-2-hot { - temperature = <120000>; + gpuss_2_alert0: gpuss-2-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-2-critical { @@ -7262,16 +7283,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_2_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-3-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 3>; trips { - gpuss-3-hot { - temperature = <120000>; + gpuss_3_alert0: gpuss-3-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-3-critical { @@ -7280,16 +7310,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_3_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-4-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 4>; trips { - gpuss-4-hot { - temperature = <120000>; + gpuss_4_alert0: gpuss-4-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-4-critical { @@ -7298,16 +7337,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_4_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-5-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 5>; trips { - gpuss-5-hot { - temperature = <120000>; + gpuss_5_alert0: gpuss-5-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-5-critical { @@ -7316,16 +7364,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_5_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-6-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 6>; trips { - gpuss-6-hot { - temperature = <120000>; + gpuss_6_alert0: gpuss-6-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-6-critical { @@ -7334,16 +7391,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_6_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-7-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 7>; trips { - gpuss-7-hot { - temperature = <120000>; + gpuss_7_alert0: gpuss-7-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-7-critical { @@ -7352,16 +7418,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_7_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-8-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 8>; trips { - gpuss-8-hot { - temperature = <120000>; + gpuss_8_alert0: gpuss-8-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-8-critical { @@ -7370,16 +7445,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_8_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-9-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 9>; trips { - gpuss-9-hot { - temperature = <120000>; + gpuss_9_alert0: gpuss-9-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-9-critical { @@ -7388,12 +7472,26 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_9_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-10-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 10>; trips { + gpuss_10_alert0: gpuss-10-alert0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; gpuss-10-hot { temperature = <120000>; hysteresis = <5000>; @@ -7406,6 +7504,13 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_10_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddr-thermal { From 4d6a1d700a682ffb92cfe8cbf51a288125bcabd8 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 26 Mar 2026 20:20:28 -0700 Subject: [PATCH 0077/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add SoCCP for Kaanapali SoC Add remoteproc PAS loader for SoCCP with its SMP2P. On Kaanapali, it is brought up by bootloader, so set the status "okay". Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260326-knp-soccp-dt-v1-1-a60c2ae36e9b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 72 +++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 714cb21a47c81..16fd724b6788c 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -513,6 +513,32 @@ }; }; + smp2p-soccp { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <19>; + + soccp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + soccp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; @@ -1522,6 +1548,52 @@ }; }; + remoteproc_soccp: remoteproc-soccp@d00000 { + compatible = "qcom,kaanapali-soccp-pas"; + reg = <0x0 0x00d00000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem>; + + qcom,smem-states = <&soccp_smp2p_out 0>, + <&soccp_smp2p_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + status = "okay"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <19>; + label = "soccp"; + }; + }; + ipcc: mailbox@1106000 { compatible = "qcom,kaanapali-ipcc", "qcom,ipcc"; reg = <0x0 0x01106000 0x0 0x1000>; From 85197b9ba165e38a62e7a429c875a4820b1d7f8e Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 26 Mar 2026 20:20:29 -0700 Subject: [PATCH 0078/1058] FROMLIST: arm64: dts: qcom: kaanapali-qrd: Add SoCCP node Add SoCCP node on Kaanapali QRD board. Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260326-knp-soccp-dt-v1-2-a60c2ae36e9b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index e20cf30d3dea4..ffe6bdd3e3db2 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -799,6 +799,11 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; +}; + &tlmm { gpio-reserved-ranges = <36 4>, /* NFC eSE SPI */ <74 1>, /* eSE */ From 09d76ec1d840f503ec946cc8055b1c4988b18d73 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 26 Mar 2026 20:20:30 -0700 Subject: [PATCH 0079/1058] FROMLIST: arm64: dts: qcom: kaanapali-mtp: Add SoCCP node Add SoCCP node on Kaanapali MTP board. Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260326-knp-soccp-dt-v1-3-a60c2ae36e9b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index f9a3494114d44..725ea04246a2f 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1089,6 +1089,11 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; +}; + &sdhc_2 { cd-gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; From f8ca9c3dfd191a427c6da4d9d910a683b9b95d70 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 1 Jun 2026 16:59:22 +0800 Subject: [PATCH 0080/1058] FROMLIST: arm64: dts: qcom: kaanapali: add reboot-mode support Add PSCI SYSTEM_RESET2 reboot-modes for kaanapali-mtp and kaanapali-qrd for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Link: https://lore.kernel.org/all/20260529-psci_sys_reset-dt-changes-for-pakala-v1-2-7c32161cf50b@oss.qualcomm.com/ Signed-off-by: Xin Liu Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 7 +++++++ arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 7 +++++++ arch/arm64/boot/dts/qcom/kaanapali.dtsi | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 725ea04246a2f..e11096fc641aa 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1366,3 +1366,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index ffe6bdd3e3db2..7d3604ea0ec2a 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -861,3 +861,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 16fd724b6788c..3a5c8a0b6ab72 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -274,7 +274,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From ecb431137e79251e9fcc2e5b1fb9cb93b46c7a51 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Sun, 10 May 2026 20:18:17 +0530 Subject: [PATCH 0081/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add qcrypto node support Add qcrypto and cryptobam support for kaanapali target. Signed-off-by: Kuldeep Singh Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/lkml/20260424-knp_qce-v1-3-813e18f8f355@oss.qualcomm.com/ Signed-off-by: Kumar Kartik --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 3a5c8a0b6ab72..67ddcc4e80737 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -2626,6 +2626,31 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v2.0.0"; + reg = <0x0 0x01dc4000 0x0 0x22000>; + interrupts = ; + #dma-cells = <1>; + iommus = <&apps_smmu 0xc0 0x0>, + <&apps_smmu 0xc1 0x0>; + qcom,ee = <0>; + qcom,num-ees = <4>; + num-channels = <20>; + qcom,controlled-remotely; + }; + + crypto: crypto@1dfa000 { + compatible = "qcom,kaanapali-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0x0 0x01dfa000 0x0 0x6000>; + interconnects = <&aggre_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "memory"; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0xc0 0x0>, + <&apps_smmu 0xc1 0x0>; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x01f40000 0x0 0x20000>; From 5efed62669d9e3e5f81e9f6a3e1a6dc88f681a75 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Wed, 10 Jun 2026 12:17:08 +0530 Subject: [PATCH 0082/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add TRNG node Add the kaanpali nodes for the True Random Number Generator (TRNG). Signed-off-by: Kuldeep Singh Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/lkml/20260423-knp_rng-v1-1-9df6c0391a8f@oss.qualcomm.com/ Signed-off-by: Kumar Kartik --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 67ddcc4e80737..838ba4cb41bf7 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -1594,6 +1594,11 @@ }; }; + rng: rng@10c3000 { + compatible = "qcom,kaanapali-trng", "qcom,trng"; + reg = <0x0 0x010c3000 0x0 0x1000>; + }; + ipcc: mailbox@1106000 { compatible = "qcom,kaanapali-ipcc", "qcom,ipcc"; reg = <0x0 0x01106000 0x0 0x1000>; From 553b0289095607f78033292c852e95fb71a0804c Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:45 -0800 Subject: [PATCH 0083/1058] FROMLIST: coresight-replicator: Defer probe when associated CPUs are offline Per-cluster replicators rely on the associated CPU cluster being online to securely access registers during initialization. If all CPUs in the cluster are offline during probe, these operations fail. Support deferred initialization for these devices: 1. Track replicators that fail to probe due to offline CPUs in a global list. 2. Register a CPU hotplug notifier (`replicator_online_cpu`) to detect when a relevant CPU comes online. 3. Upon CPU online, retry the hardware initialization and registration with the CoreSight framework. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-5-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../coresight/coresight-replicator.c | 66 +++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index c8d2a6082a97f..0d34af1042218 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -25,6 +25,10 @@ #define REPLICATOR_IDFILTER0 0x000 #define REPLICATOR_IDFILTER1 0x004 +static LIST_HEAD(replicator_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + /** * struct replicator_drvdata - specifics associated to a replicator component * @base: memory mapped base address for this component. Also indicates @@ -35,6 +39,8 @@ * @spinlock: serialize enable/disable operations. * @check_idfilter_val: check if the context is lost upon clock removal. * @supported_cpus: Represent the CPUs related to this funnel. + * @dev: pointer to the device associated with this replicator. + * @link: link to the delay_probed list. */ struct replicator_drvdata { void __iomem *base; @@ -44,6 +50,8 @@ struct replicator_drvdata { raw_spinlock_t spinlock; bool check_idfilter_val; struct cpumask *supported_cpus; + struct device *dev; + struct list_head link; }; struct replicator_smp_arg { @@ -392,7 +400,7 @@ static int replicator_probe(struct device *dev, struct resource *res) drvdata->supported_cpus = replicator_get_supported_cpus(dev); if (!drvdata->supported_cpus) return -EINVAL; - + drvdata->dev = dev; cpus_read_lock(); for_each_cpu(cpu, drvdata->supported_cpus) { ret = smp_call_function_single(cpu, @@ -400,10 +408,15 @@ static int replicator_probe(struct device *dev, struct resource *res) if (!ret) break; } - cpus_read_unlock(); - if (ret) + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &replicator_delay_probe); + cpus_read_unlock(); return 0; + } + + cpus_read_unlock(); } else if (res) { replicator_init_hw(drvdata); } @@ -417,8 +430,13 @@ static int replicator_remove(struct device *dev) { struct replicator_drvdata *drvdata = dev_get_drvdata(dev); - if (drvdata->csdev) + if (drvdata->csdev) { coresight_unregister(drvdata->csdev); + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } + return 0; } @@ -550,14 +568,54 @@ static struct amba_driver dynamic_replicator_driver = { .id_table = dynamic_replicator_ids, }; +static int replicator_online_cpu(unsigned int cpu) +{ + struct replicator_drvdata *drvdata, *tmp; + int ret; + + spin_lock(&delay_lock); + list_for_each_entry_safe(drvdata, tmp, &replicator_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + list_del(&drvdata->link); + spin_unlock(&delay_lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + replicator_clear_self_claim_tag(drvdata); + replicator_reset(drvdata); + replicator_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + spin_lock(&delay_lock); + } + } + spin_unlock(&delay_lock); + return 0; +} + static int __init replicator_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-replicator:online", + replicator_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver); } static void __exit replicator_exit(void) { coresight_remove_driver(&dynamic_replicator_driver, &replicator_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(replicator_init); From 58bbc4c81a4dc96014b2a59a4465d0cceb4fbf2c Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:46 -0800 Subject: [PATCH 0084/1058] FROMLIST: coresight-replicator: Update management interface for CPU-bound devices Standard system replicators allow direct register access from any CPU. However, replicators associated with specific CPU clusters share the cluster's power domain and require access via a CPU within that domain. Replace the standard `coresight_simple_reg*` accessors with custom handlers (`coresight_replicator_reg*`) to support these devices: - For cluster-bound replicators (indicated by `supported_cpus`), use `smp_call_function_single()` to read registers on an associated CPU. - For standard replicators, retain the direct access behavior. This ensures correct operation for per-cluster replicators while maintaining compatibility for existing system-level devices. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-6-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../coresight/coresight-replicator.c | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 0d34af1042218..d4f31f03cf23c 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -57,6 +57,7 @@ struct replicator_drvdata { struct replicator_smp_arg { struct replicator_drvdata *drvdata; int outport; + u32 offset; int rc; }; @@ -285,9 +286,65 @@ static const struct coresight_ops replicator_cs_ops = { .link_ops = &replicator_link_ops, }; +static void replicator_read_register_smp_call(void *info) +{ + struct replicator_smp_arg *arg = info; + + arg->rc = readl_relaxed(arg->drvdata->base + arg->offset); +} + +static ssize_t coresight_replicator_reg32_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct replicator_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); + unsigned long flags; + struct replicator_smp_arg arg = { 0 }; + u32 val; + int ret, cpu; + + pm_runtime_get_sync(dev->parent); + + if (!drvdata->supported_cpus) { + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + val = readl_relaxed(drvdata->base + cs_attr->off); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + } else { + arg.drvdata = drvdata; + arg.offset = cs_attr->off; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + replicator_read_register_smp_call, + &arg, 1); + if (!ret) + break; + } + if (!ret) { + val = arg.rc; + } else { + pm_runtime_put_sync(dev->parent); + return ret; + } + } + + pm_runtime_put_sync(dev->parent); + + return sysfs_emit(buf, "0x%x\n", val); +} + +#define coresight_replicator_reg32(name, offset) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_replicator_reg32_show, NULL), \ + offset \ + } \ + })[0].attr.attr) + static struct attribute *replicator_mgmt_attrs[] = { - coresight_simple_reg32(idfilter0, REPLICATOR_IDFILTER0), - coresight_simple_reg32(idfilter1, REPLICATOR_IDFILTER1), + coresight_replicator_reg32(idfilter0, REPLICATOR_IDFILTER0), + coresight_replicator_reg32(idfilter1, REPLICATOR_IDFILTER1), NULL, }; From afc50e5266202470f930864462c34d67aa20a0e1 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:47 -0800 Subject: [PATCH 0085/1058] FROMLIST: coresight-tmc: Support probe and initialization for CPU cluster TMCs TMC instances associated with CPU clusters reside in the cluster's power domain. Unlike system-level TMCs, their registers are only accessible when the cluster is powered on. Standard runtime PM may not suffice to wake up a cluster from low-power states during probe, making direct register access unreliable. Refactor the probe sequence to handle these per-cluster devices safely: 1. Identify per-cluster TMCs using the "qcom,cpu-bound-components" property. 2. For such devices, use `smp_call_function_single()` to perform hardware initialization (`tmc_init_hw_config`) on a CPU within the cluster. This ensures the domain is powered during access. 3. Factor out the device registration logic into `tmc_add_coresight_dev()`. This allows common registration code to be shared between the standard probe path and the deferred probe path (used when the associated CPUs are initially offline). This change ensures reliable initialization for per-cluster TMCs while maintaining backward compatibility for standard system-level TMCs. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-7-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-tmc-core.c | 195 +++++++++++------- drivers/hwtracing/coresight/coresight-tmc.h | 6 + 2 files changed, 132 insertions(+), 69 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 6ad09995ba87c..abbf0277a9d74 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -755,56 +756,14 @@ static const struct tmc_sysfs_ops etr_sysfs_ops = { .get_trace_data = tmc_etr_get_sysfs_trace, }; -static int __tmc_probe(struct device *dev, struct resource *res) +static int tmc_add_coresight_dev(struct device *dev) { - int ret = 0; - u32 devid; - void __iomem *base; - struct coresight_platform_data *pdata = NULL; - struct tmc_drvdata *drvdata; + struct tmc_drvdata *drvdata = dev_get_drvdata(dev); struct coresight_desc desc = { 0 }; const char *dev_list = NULL; + int ret = 0; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - dev_set_drvdata(dev, drvdata); - - ret = coresight_get_enable_clocks(dev, &drvdata->pclk, &drvdata->atclk); - if (ret) - return ret; - - ret = -ENOMEM; - - /* Validity for the resource is already checked by the AMBA core */ - base = devm_ioremap_resource(dev, res); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto out; - } - - drvdata->base = base; - desc.access = CSDEV_ACCESS_IOMEM(base); - - raw_spin_lock_init(&drvdata->spinlock); - - devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); - drvdata->config_type = BMVAL(devid, 6, 7); - drvdata->memwidth = tmc_get_memwidth(devid); - /* This device is not associated with a session */ - drvdata->pid = -1; - drvdata->etr_mode = ETR_MODE_AUTO; - - if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { - drvdata->size = tmc_etr_get_default_buffer_size(dev); - drvdata->max_burst_size = tmc_etr_get_max_burst_size(dev); - } else { - drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; - } - - tmc_get_reserved_region(dev); - + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); desc.dev = dev; switch (drvdata->config_type) { @@ -821,9 +780,9 @@ static int __tmc_probe(struct device *dev, struct resource *res) desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM; desc.ops = &tmc_etr_cs_ops; - ret = tmc_etr_setup_caps(dev, devid, &desc.access); + ret = tmc_etr_setup_caps(dev, drvdata->devid, &desc.access); if (ret) - goto out; + return ret; idr_init(&drvdata->idr); mutex_init(&drvdata->idr_mutex); dev_list = "tmc_etr"; @@ -841,44 +800,141 @@ static int __tmc_probe(struct device *dev, struct resource *res) break; default: pr_err("%s: Unsupported TMC config\n", desc.name); - ret = -EINVAL; - goto out; + return -EINVAL; } desc.name = coresight_alloc_device_name(dev_list, dev); - if (!desc.name) { - ret = -ENOMEM; + if (!desc.name) + return -ENOMEM; + + drvdata->desc_name = desc.name; + + desc.pdata = dev->platform_data; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + + drvdata->miscdev.name = desc.name; + drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; + drvdata->miscdev.fops = &tmc_fops; + ret = misc_register(&drvdata->miscdev); + if (ret) + coresight_unregister(drvdata->csdev); + + return ret; +} + +static void tmc_clear_self_claim_tag(struct tmc_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static void tmc_init_hw_config(struct tmc_drvdata *drvdata) +{ + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + drvdata->config_type = BMVAL(devid, 6, 7); + drvdata->memwidth = tmc_get_memwidth(devid); + drvdata->devid = devid; + drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; + tmc_clear_self_claim_tag(drvdata); +} + +static void tmc_init_on_cpu(void *info) +{ + struct tmc_drvdata *drvdata = info; + + tmc_init_hw_config(drvdata); +} + +static struct cpumask *tmc_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + +static int __tmc_probe(struct device *dev, struct resource *res) +{ + int cpu, ret = 0; + void __iomem *base; + struct coresight_platform_data *pdata = NULL; + struct tmc_drvdata *drvdata; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + dev_set_drvdata(dev, drvdata); + + ret = coresight_get_enable_clocks(dev, &drvdata->pclk, &drvdata->atclk); + if (ret) + return ret; + + ret = -ENOMEM; + + /* Validity for the resource is already checked by the AMBA core */ + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); goto out; } + drvdata->base = base; + + raw_spin_lock_init(&drvdata->spinlock); + /* This device is not associated with a session */ + drvdata->pid = -1; + drvdata->etr_mode = ETR_MODE_AUTO; + tmc_get_reserved_region(dev); + pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) { ret = PTR_ERR(pdata); goto out; } dev->platform_data = pdata; - desc.pdata = pdata; - coresight_clear_self_claim_tag(&desc.access); - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) { - ret = PTR_ERR(drvdata->csdev); - goto out; + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = tmc_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_init_on_cpu, drvdata, 1); + if (!ret) + break; + } + cpus_read_unlock(); + if (ret) { + ret = 0; + goto out; + } + } else { + tmc_init_hw_config(drvdata); } - drvdata->miscdev.name = desc.name; - drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; - drvdata->miscdev.fops = &tmc_fops; - ret = misc_register(&drvdata->miscdev); - if (ret) { - coresight_unregister(drvdata->csdev); - goto out; + if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { + drvdata->size = tmc_etr_get_default_buffer_size(dev); + drvdata->max_burst_size = tmc_etr_get_max_burst_size(dev); } + ret = tmc_add_coresight_dev(dev); + out: if (is_tmc_crashdata_valid(drvdata) && !tmc_prepare_crashdata(drvdata)) - register_crash_dev_interface(drvdata, desc.name); + register_crash_dev_interface(drvdata, drvdata->desc_name); return ret; } @@ -924,10 +980,12 @@ static void __tmc_remove(struct device *dev) * etb fops in this case, device is there until last file * handler to this device is closed. */ - misc_deregister(&drvdata->miscdev); + if (!drvdata->supported_cpus) + misc_deregister(&drvdata->miscdev); if (drvdata->crashdev.fops) misc_deregister(&drvdata->crashdev); - coresight_unregister(drvdata->csdev); + if (drvdata->csdev) + coresight_unregister(drvdata->csdev); } static void tmc_remove(struct amba_device *adev) @@ -982,7 +1040,6 @@ static void tmc_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; - __tmc_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); } diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index a15e2f93f16a5..fc514cd69df2a 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -263,6 +263,9 @@ struct etr_buf_node { * Used by ETR/ETF. * @etr_buf_list: List that is used to manage allocated etr_buf. * @sysfs_ops: Read operations for the sysfs mode. + * @supported_cpus: Represent the CPUs related to this TMC. + * @devid: TMC variant ID inferred from the device configuration register. + * @desc_name: Name to be used while creating crash interface. */ struct tmc_drvdata { struct clk *atclk; @@ -295,6 +298,9 @@ struct tmc_drvdata { struct tmc_resrv_buf crash_mdata; struct list_head etr_buf_list; const struct tmc_sysfs_ops *sysfs_ops; + struct cpumask *supported_cpus; + u32 devid; + const char *desc_name; }; /** From 2000119ee5f5de2f4768745421c628d3d6b4d617 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:48 -0800 Subject: [PATCH 0086/1058] FROMLIST: coresight-tmc-etf: Refactor enable function for CPU cluster ETF support TMC-ETF devices associated with specific CPU clusters share the cluster's power domain. Accessing their registers requires the cluster to be powered on, which can only be guaranteed by running code on a CPU within that cluster. Refactor the enablement logic to support this requirement: 1. Split `tmc_etf_enable_hw` and `tmc_etb_enable_hw` into local and SMP-aware variants: - `*_local`: Performs the actual register access. - `*_smp_call`: Wrapper for `smp_call_function_single`. - The main entry point now detects if the device is CPU-bound and uses `smp_call_function_single` to execute the local variant on an appropriate CPU if necessary. 2. Adjust locking in `tmc_enable_etf_sink_sysfs` and `tmc_enable_etf_link`: - Drop the spinlock before calling `tmc_etf_enable_hw`. This is necessary because `smp_call_function_single` (used for cross-CPU calls) may require interrupts enabled or might sleep/wait, which is unsafe under a spinlock. - Re-acquire the lock afterwards to update driver state. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-8-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-tmc-etf.c | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 8882b1c4cdc05..11357788e9d93 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -47,7 +47,7 @@ static int __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) return rc; } -static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) +static int tmc_etb_enable_hw_local(struct tmc_drvdata *drvdata) { int rc = coresight_claim_device(drvdata->csdev); @@ -60,6 +60,36 @@ static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) return rc; } +struct tmc_smp_arg { + struct tmc_drvdata *drvdata; + int rc; +}; + +static void tmc_etb_enable_hw_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = tmc_etb_enable_hw_local(arg->drvdata); +} + +static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) +{ + int cpu, ret; + struct tmc_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return tmc_etb_enable_hw_local(drvdata); + + arg.drvdata = drvdata; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_etb_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata) { char *bufp; @@ -130,7 +160,7 @@ static int __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) return rc; } -static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) +static int tmc_etf_enable_hw_local(struct tmc_drvdata *drvdata) { int rc = coresight_claim_device(drvdata->csdev); @@ -143,6 +173,32 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) return rc; } +static void tmc_etf_enable_hw_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = tmc_etf_enable_hw_local(arg->drvdata); +} + +static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) +{ + int cpu, ret; + struct tmc_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return tmc_etf_enable_hw_local(drvdata); + + arg.drvdata = drvdata; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_etf_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; @@ -228,7 +284,11 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) used = true; drvdata->buf = buf; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + ret = tmc_etb_enable_hw(drvdata); + + raw_spin_lock_irqsave(&drvdata->spinlock, flags); if (!ret) { coresight_set_mode(csdev, CS_MODE_SYSFS); csdev->refcnt++; @@ -291,7 +351,11 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, break; } - ret = tmc_etb_enable_hw(drvdata); + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) + break; + + ret = tmc_etb_enable_hw_local(drvdata); if (!ret) { /* Associate with monitored process. */ drvdata->pid = pid; @@ -376,19 +440,22 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, return -EBUSY; } - if (csdev->refcnt == 0) { + if (csdev->refcnt == 0) + first_enable = true; + + if (!first_enable) + csdev->refcnt++; + + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + if (first_enable) { ret = tmc_etf_enable_hw(drvdata); if (!ret) { coresight_set_mode(csdev, CS_MODE_SYSFS); - first_enable = true; + csdev->refcnt++; + dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); } } - if (!ret) - csdev->refcnt++; - raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); return ret; } From 3b5619d02b45086ec692cf260dd2e2a7ff19df65 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:49 -0800 Subject: [PATCH 0087/1058] FROMLIST: coresight-tmc: Update management interface for CPU-bound TMCs The current TMC management interface (sysfs attributes) assumes that device registers can be accessed directly from any CPU. However, for TMCs associated with specific CPU clusters, registers must be accessed from a CPU within that cluster. Replace the standard `coresight_simple_reg*` handlers with custom accessors (`coresight_tmc_reg*`). These new handlers check if the TMC is bound to a specific set of CPUs: - If bound, they use `smp_call_function_single()` to read the register on an appropriate CPU. - If not bound (global TMC), they fall back to direct access. This ensures correct register reads for per-cluster TMC devices while maintaining backward compatibility for global TMCs. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-9-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-tmc-core.c | 137 ++++++++++++++++-- 1 file changed, 123 insertions(+), 14 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index abbf0277a9d74..4224ee21570c5 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -432,21 +432,130 @@ static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid) return memwidth; } +struct tmc_smp_arg { + struct tmc_drvdata *drvdata; + u32 offset; + int rc; +}; + +static void tmc_read_reg_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = readl_relaxed(arg->drvdata->base + arg->offset); +} + +static u32 cpu_tmc_read_reg(struct tmc_drvdata *drvdata, u32 offset) +{ + struct tmc_smp_arg arg = { + .drvdata = drvdata, + .offset = offset, + }; + int cpu, ret = 0; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_read_reg_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + + return ret; +} + +static ssize_t coresight_tmc_reg32_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); + int ret; + u32 val; + + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; + + if (!drvdata->supported_cpus) + val = readl_relaxed(drvdata->base + cs_attr->off); + else + val = cpu_tmc_read_reg(drvdata, cs_attr->off); + + pm_runtime_put(dev->parent); + + if (ret < 0) + return ret; + else + return sysfs_emit(buf, "0x%x\n", val); +} + +static ssize_t coresight_tmc_reg64_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); + int ret; + u64 val; + + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; + if (!drvdata->supported_cpus) { + val = readl_relaxed(drvdata->base + cs_attr->lo_off) | + ((u64)readl_relaxed(drvdata->base + cs_attr->hi_off) << 32); + } else { + ret = cpu_tmc_read_reg(drvdata, cs_attr->lo_off); + + if (ret < 0) + goto out; + + val = ret; + + ret = cpu_tmc_read_reg(drvdata, cs_attr->hi_off); + if (ret < 0) + goto out; + + val |= ((u64)ret << 32); + } + +out: + pm_runtime_put_sync(dev->parent); + if (ret < 0) + return ret; + else + return sysfs_emit(buf, "0x%llx\n", val); +} + +#define coresight_tmc_reg32(name, offset) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_tmc_reg32_show, NULL), \ + offset \ + } \ + })[0].attr.attr) +#define coresight_tmc_reg64(name, lo_off, hi_off) \ + (&((struct cs_pair_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_tmc_reg64_show, NULL), \ + lo_off, hi_off \ + } \ + })[0].attr.attr) static struct attribute *coresight_tmc_mgmt_attrs[] = { - coresight_simple_reg32(rsz, TMC_RSZ), - coresight_simple_reg32(sts, TMC_STS), - coresight_simple_reg64(rrp, TMC_RRP, TMC_RRPHI), - coresight_simple_reg64(rwp, TMC_RWP, TMC_RWPHI), - coresight_simple_reg32(trg, TMC_TRG), - coresight_simple_reg32(ctl, TMC_CTL), - coresight_simple_reg32(ffsr, TMC_FFSR), - coresight_simple_reg32(ffcr, TMC_FFCR), - coresight_simple_reg32(mode, TMC_MODE), - coresight_simple_reg32(pscr, TMC_PSCR), - coresight_simple_reg32(devid, CORESIGHT_DEVID), - coresight_simple_reg64(dba, TMC_DBALO, TMC_DBAHI), - coresight_simple_reg32(axictl, TMC_AXICTL), - coresight_simple_reg32(authstatus, TMC_AUTHSTATUS), + coresight_tmc_reg32(rsz, TMC_RSZ), + coresight_tmc_reg32(sts, TMC_STS), + coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI), + coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI), + coresight_tmc_reg32(trg, TMC_TRG), + coresight_tmc_reg32(ctl, TMC_CTL), + coresight_tmc_reg32(ffsr, TMC_FFSR), + coresight_tmc_reg32(ffcr, TMC_FFCR), + coresight_tmc_reg32(mode, TMC_MODE), + coresight_tmc_reg32(pscr, TMC_PSCR), + coresight_tmc_reg32(devid, CORESIGHT_DEVID), + coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI), + coresight_tmc_reg32(axictl, TMC_AXICTL), + coresight_tmc_reg32(authstatus, TMC_AUTHSTATUS), NULL, }; From 68e358748447270f2bdd2014f1ff90a1da8730c3 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:45 -0700 Subject: [PATCH 0088/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add camss node Add node for the Kaanapali camera subsystem. Reviewed-by: Vladimir Zapolskiy Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-knp-camera-v1-1-a18e289163fd@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 228 +++++++++++++++++++----- 1 file changed, 179 insertions(+), 49 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 838ba4cb41bf7..a9e4ab30e2a8f 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3526,47 +3526,175 @@ }; }; - usb_hsphy: phy@88e3000 { - compatible = "qcom,kaanapali-m31-eusb2-phy", - "qcom,sm8750-m31-eusb2-phy"; - reg = <0x0 0x88e3000 0x0 0x29c>; - - clocks = <&tcsr TCSR_USB2_CLKREF_EN>; - clock-names = "ref"; - - resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; - - #phy-cells = <0>; - - status = "disabled"; - }; - - usb_dp_qmpphy: phy@88e8000 { - compatible = "qcom,kaanapali-qmp-usb3-dp-phy", - "qcom,sm8750-qmp-usb3-dp-phy"; - reg = <0x0 0x088e8000 0x0 0x4000>; - - clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, - <&tcsr TCSR_USB3_CLKREF_EN>, - <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, - <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; - clock-names = "aux", - "ref", - "com_aux", - "usb3_pipe"; - - resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, - <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; - reset-names = "phy", - "common"; - - power-domains = <&gcc GCC_USB3_PHY_GDSC>; - - #clock-cells = <1>; - #phy-cells = <1>; - - orientation-switch; + camss: isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x1300>, + <0x0 0x092f0000 0x0 0x1300>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; status = "disabled"; ports { @@ -3575,24 +3703,26 @@ port@0 { reg = <0>; - - usb_dp_qmpphy_out: endpoint { - }; }; port@1 { reg = <1>; - - usb_dp_qmpphy_usb_ss_in: endpoint { - remote-endpoint = <&usb_dwc3_ss>; - }; }; port@2 { reg = <2>; + }; - usb_dp_qmpphy_dp_in: endpoint { - }; + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; }; }; }; From b06f8d023370bb0d3779164ffd8f2a55a0174460 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:46 -0700 Subject: [PATCH 0089/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add CCI definitions Qualcomm Kaanapali SoC has three Camera Control Interface (CCI). Each controller contains two I2C hosts. Reviewed-by: Vladimir Zapolskiy Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-knp-camera-v1-2-a18e289163fd@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 282 ++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index a9e4ab30e2a8f..03b185a9a5deb 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3727,6 +3727,96 @@ }; }; + cci0: cci@941b000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@941c000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@941d000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,kaanapali-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; @@ -4284,6 +4374,198 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio66", "gpio67"; From 70a3889e9c01f2f8ed66128e5862509973d0b1ce Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:47 -0700 Subject: [PATCH 0090/1058] FROMLIST: arm64: dts: qcom: kaanapali: Add camera MCLK pinctrl Define pinctrl definitions to enable camera master clocks on Kaanapali. Reviewed-by: Vladimir Zapolskiy Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-knp-camera-v1-3-a18e289163fd@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 03b185a9a5deb..bb23016d322fa 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -4374,6 +4374,62 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_asc_mclk2"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_asc_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { sda-pins { pins = "gpio109"; From f6ed56b503a15dc168700ec4f02e0365680c2cf4 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 24 Jun 2026 17:02:04 +0800 Subject: [PATCH 0091/1058] FROMLIST: arm64: dts: qcom: kaanapali: fix traceNoC probe issue The AMBA bus attempts to read the CID/PID of a device before invoking its probe function if the arm,primecell-periphid property is absent. This causes a deferred probe issue for the TraceNoC device, as the CID/PID cannot be read from the periphid register. Add the arm,primecell-periphid property to bypass the AMBA bus check and resolve the probe issue. Link: https://lore.kernel.org/r/20260624-fix-tracenoc-probe-issue-v2-0-786520f62f21@oss.qualcomm.com Fixes: f73959d86c15 ("arm64: dts: qcom: kaanapali: add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index bb23016d322fa..192a5caa6ccea 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -5229,6 +5229,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + arm,primecell-periphid = <0x000f0c00>; in-ports { #address-cells = <1>; From a9e58d34187fc1b8d8486745005e464e246b6ca3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:57 +0000 Subject: [PATCH 0092/1058] FROMLIST: phy: dphy: Add lane_positions to DPHY config struct Add lane_positions to the DPHY configuration struct. This data-field represents the physical positions of the data-lanes indexed by lane number. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-1-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 1ac128d78dfeb..c7eb11c41d7ec 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -6,6 +6,8 @@ #ifndef __PHY_MIPI_DPHY_H_ #define __PHY_MIPI_DPHY_H_ +#define PHY_MIPI_DPHY_MAX_DATA_LANES 4 + /** * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set * @@ -269,10 +271,19 @@ struct phy_configure_opts_mipi_dphy { /** * @lanes: * - * Number of active, consecutive, data lanes, starting from - * lane 0, used for the transmissions. + * Number of active data lanes used for the transmission. + * When @lane_positions is not populated, lanes are consecutive + * starting from lane 0. */ unsigned char lanes; + + /** + * @lane_positions: + * + * Array representing the physical positions of the data-lanes. + * Indexed by logical lane number. + */ + unsigned char lane_positions[PHY_MIPI_DPHY_MAX_DATA_LANES]; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From 2a79746a0304d3912a8c59ec397f95dd0f518dbf Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:58 +0000 Subject: [PATCH 0093/1058] FROMLIST: phy: dphy: Add lane_polarities to DPHY config struct Pass an array of data-lane polarities from controller to PHY. A true value means the lane polarity is inverted. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-2-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index c7eb11c41d7ec..3e0333b5a1a71 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -284,6 +284,14 @@ struct phy_configure_opts_mipi_dphy { * Indexed by logical lane number. */ unsigned char lane_positions[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @lane_polarities: + * + * Array representing data-lane polarities. True means inverted. + * Indexed by logical lane number. + */ + bool lane_polarities[PHY_MIPI_DPHY_MAX_DATA_LANES]; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From f77a66b1e127792e52caa371a2a621b598014e6a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:59 +0000 Subject: [PATCH 0094/1058] FROMLIST: phy: dphy: Add clock_lane_position to DPHY config struct We need to identify which lane is the clock-lane as many different PHYs allow for a range of lanes, potentially any of the lanes to be the clock input lane on a PHY. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-3-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 3e0333b5a1a71..76d41580e225a 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -292,6 +292,13 @@ struct phy_configure_opts_mipi_dphy { * Indexed by logical lane number. */ bool lane_polarities[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @clock_lane_position: + * + * Physical lane number used as the clock lane. + */ + unsigned char clock_lane_position; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From cc5e12608660465924ba15f11bd84e8dc4b7edab Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:48:00 +0000 Subject: [PATCH 0095/1058] FROMLIST: phy: dphy: Add clock_lane_polarity to DPHY config struct Specify the polarity of the clock lane in DPHY mode. When true this bool means the polarity is inverted. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-4-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 76d41580e225a..f7b4ad29e6f83 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -299,6 +299,13 @@ struct phy_configure_opts_mipi_dphy { * Physical lane number used as the clock lane. */ unsigned char clock_lane_position; + + /** + * @clock_lane_polarity: + * + * Clock lane polarity. True means inverted. + */ + bool clock_lane_polarity; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From 41a3ff4bd3555ba8fd95e7114dc56af34dfcbd0c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:43 +0000 Subject: [PATCH 0096/1058] FROMLIST: dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 PHY devices. The hardware can support both CPHY, DPHY and a special split-mode DPHY. We capture those modes as: - PHY_QCOM_CSI2_MODE_DPHY - PHY_QCOM_CSI2_MODE_CPHY - PHY_QCOM_CSI2_MODE_SPLIT_DPHY The CSIPHY devices have their own pinouts on the SoC as well as their own individual voltage rails. The need to model voltage rails on a per-PHY basis leads us to define CSIPHY devices as individual nodes. Two nice outcomes in terms of schema and DT arise from this change. 1. The ability to define on a per-PHY basis voltage rails. 2. The ability to require those voltage. We have had a complete bodge upstream for this where a single set of voltage rail for all CSIPHYs has been buried inside of CAMSS. Much like the I2C bus which is dedicated to Camera sensors - the CCI bus in CAMSS parlance, the CSIPHY devices should be individually modelled. Link: https://lore.kernel.org/all/20260326-x1e-csi2-phy-v5-1-0c0fc7f5c01b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 130 ++++++++++++++++++ include/dt-bindings/phy/phy-qcom-mipi-csi2.h | 15 ++ 2 files changed, 145 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml create mode 100644 include/dt-bindings/phy/phy-qcom-mipi-csi2.h diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml new file mode 100644 index 0000000000000..63114151104b4 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm CSI2 PHY + +maintainers: + - Bryan O'Donoghue + +description: + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY + modes. + +properties: + compatible: + const: qcom,x1e80100-csi2-phy + + reg: + maxItems: 1 + + "#phy-cells": + const: 1 + description: + The single cell specifies the PHY operating mode. + See include/dt-bindings/phy/phy-qcom-mipi-csi2.h for valid values. + + clocks: + maxItems: 2 + + clock-names: + items: + - const: core + - const: timer + + interrupts: + maxItems: 1 + + operating-points-v2: + maxItems: 1 + + power-domains: + items: + - description: MXC or MXA voltage rail + - description: MMCX voltage rail + + power-domain-names: + items: + - const: mx + - const: mmcx + + vdda-0p9-supply: + description: Phandle to a 0.9V regulator supply to a PHY. + + vdda-1p2-supply: + description: Phandle to 1.2V regulator supply to a PHY. + +required: + - compatible + - reg + - "#phy-cells" + - clocks + - clock-names + - interrupts + - operating-points-v2 + - power-domains + - power-domain-names + - vdda-0p9-supply + - vdda-1p2-supply + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + csiphy4: csiphy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0x0ace4000 0x2000>; + #phy-cells = <1>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + }; + + csiphy_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + isp@acb7000 { + phys = <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + }; diff --git a/include/dt-bindings/phy/phy-qcom-mipi-csi2.h b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..fa48fd75c58d8 --- /dev/null +++ b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Qualcomm MIPI CSI2 PHY constants + * + * Copyright (C) 2026 Linaro Limited + */ + +#ifndef __DT_BINDINGS_PHY_MIPI_CSI2__ +#define __DT_BINDINGS_PHY_MIPI_CSI2__ + +#define PHY_QCOM_CSI2_MODE_DPHY 0 +#define PHY_QCOM_CSI2_MODE_CPHY 1 +#define PHY_QCOM_CSI2_MODE_SPLIT_DPHY 2 + +#endif /* __DT_BINDINGS_PHY_MIPI_CSI2__ */ From 989460ec8af2ff7677105b08e91f28a44aec7a2a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:44 +0000 Subject: [PATCH 0097/1058] FROMLIST: phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Add a new MIPI CSI2 driver in DPHY mode initially. The entire set of existing CAMSS CSI PHY init sequences are imported in order to save time and effort in later patches. The following devices are supported in this drop: "qcom,x1e80100-csi2-phy" In-line with other PHY drivers the process node is included in the name. Data-lane and clock lane positioning and polarity selection via newly amended struct phy_configure_opts_mipi_dphy{} is supported. The Qualcomm 3PH class of PHYs can do both DPHY and CPHY mode. For now only DPHY is supported. In porting some of the logic over from camss-csiphy*.c to here its also possible to rationalise some of the code. In particular use of regulator_bulk and clk_bulk as well as dropping the seemingly useless and unused interrupt handler. The PHY sequences and a lot of the logic that goes with them are well proven in CAMSS and mature so the main thing to watch out for here is how to get the right sequencing of regulators, clocks and register-writes. The register init sequence table is imported verbatim from the existing CAMSS csiphy driver. A follow-up series will rework the table to extract the repetitive per-lane pattern into a loop. Link: https://lore.kernel.org/all/20260326-x1e-csi2-phy-v5-2-0c0fc7f5c01b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- MAINTAINERS | 11 + drivers/phy/qualcomm/Kconfig | 13 + drivers/phy/qualcomm/Makefile | 5 + .../qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 361 ++++++++++++++++++ .../phy/qualcomm/phy-qcom-mipi-csi2-core.c | 298 +++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 95 +++++ 6 files changed, 783 insertions(+) create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2.h diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a99..05bfd1649e445 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22296,6 +22296,17 @@ S: Maintained F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml F: drivers/media/platform/qcom/iris/ +QUALCOMM MIPI CSI2 PHY DRIVER +M: Bryan O'Donoghue +L: linux-phy@lists.infradead.org +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h +F: include/dt-bindings/phy/phy-qcom-mipi-csi2* + QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 60a0ead127fa9..ea33025a40fd0 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -28,6 +28,19 @@ config PHY_QCOM_EDP Enable this driver to support the Qualcomm eDP PHY found in various Qualcomm chipsets. +config PHY_QCOM_MIPI_CSI2 + tristate "Qualcomm MIPI CSI2 PHY driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on COMMON_CLK + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the MIPI CSI2 PHY driver found in various + Qualcomm chipsets. This PHY is used to connect MIPI CSI2 + camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem + CAMSS. + config PHY_QCOM_IPQ4019_USB tristate "Qualcomm IPQ4019 USB PHY driver" depends on OF && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index b71a6a0bed3f1..382cb594b06b6 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o + +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ + phy-qcom-mipi-csi2-3ph-dphy.o +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c new file mode 100644 index 0000000000000..b1eb2b28b2da2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0 + * + * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2016-2025 Linaro Ltd. + */ + +#include +#include +#include +#include + +#include "phy-qcom-mipi-csi2.h" + +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n)) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n)) + +/* + * 3 phase CSI has 19 common status regs with only 0-10 being used + * and 11-18 being reserved. + */ +#define CSI_COMMON_STATUS_NUM 11 +/* + * There are a number of common control registers + * The offset to clear the CSIPHY IRQ status starts @ 22 + * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is + * CONTROL23 and so on + */ +#define CSI_CTRL_STATUS_INDEX 22 + +/* + * There are 43 COMMON_CTRL registers with regs after # 33 being reserved + */ +#define CSI_CTRL_MAX 33 + +#define CSIPHY_DEFAULT_PARAMS 0 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SKEW_CAL 7 + +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ +static const struct +mipi_csi2phy_lane_regs lane_regs_x1e80100[] = { + /* Power up lanes 2ph mode */ + {.reg_addr = 0x1014, .reg_data = 0xd5, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x101c, .reg_data = 0x7a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x00a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0000, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0038, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x002c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0034, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x001c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x003c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0004, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x005c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0060, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0064, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0e94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ea0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e0c, .reg_data = 0xff, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e38, .reg_data = 0x1f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0e10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x04a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0400, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0438, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x042c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0434, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x041c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x043c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0404, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x045c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0460, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0464, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x08a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0800, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0838, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x082c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0834, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x081c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x083c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0804, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x085c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0860, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0864, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0c94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ca0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c00, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c38, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0c10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c5c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c60, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c64, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, +}; + +static inline const struct mipi_csi2phy_device_regs * +csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy) +{ + return &csi2phy->soc_cfg->reg_info; +} + +static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + u32 tmp; + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + csi2phy->hw_version = tmp; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + csi2phy->hw_version |= (tmp << 8) & 0xFF00; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + csi2phy->hw_version |= (tmp << 16) & 0xFF0000; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + csi2phy->hw_version |= (tmp << 24) & 0xFF000000; + + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version); +} + +/* + * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module + * @phy_qcom_mipi_csi2: CSIPHY device + */ +static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET, + csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + usleep_range(5000, 8000); + writel(0x0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); +} + +/* + * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value + * + * Helper function to calculate settle count value. This is + * based on the CSI2 T_hs_settle parameter which in turn + * is calculated based on the CSI2 transmitter link frequency. + * + * Return settle count value or 0 if the CSI2 link frequency + * is not available + */ +static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate) +{ + u32 t_hs_prepare_max_ps; + u32 timer_period_ps; + u32 t_hs_settle_ps; + u8 settle_cnt; + u32 ui_ps; + + if (link_freq <= 0) + return 0; + + ui_ps = div_u64(PSEC_PER_SEC, link_freq); + ui_ps /= 2; + t_hs_prepare_max_ps = 85000 + 6 * ui_ps; + t_hs_settle_ps = t_hs_prepare_max_ps; + + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); + settle_cnt = t_hs_settle_ps / timer_period_ps - 6; + + return settle_cnt; +} + +static void +phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy, + u8 settle_cnt) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + const struct mipi_csi2phy_lane_regs *r = regs->init_seq; + int i, array_size = regs->lane_array_size; + u32 val; + + for (i = 0; i < array_size; i++, r++) { + switch (r->param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SKEW_CAL: + /* TODO: support application of skew from dt flag */ + continue; + default: + val = r->reg_data; + break; + } + writel(val, csi2phy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; + u8 settle_cnt; + u8 val; + int i; + + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + for (i = 0; i < cfg->num_data_lanes; i++) + val |= BIT(lane_cfg->data[i].pos * 2); + + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + val = 0x02; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); + + val = 0x00; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + + phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt); + + /* IRQ_MASK registers - disable all interrupts */ + for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) { + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i)); + } + + return 0; +} + +static void +phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); +} + +static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = { + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, + .reset = phy_qcom_mipi_csi2_reset, + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, +}; + +static const char * const x1e_clks[] = { + "core", + "timer" +}; + +static const char * const x1e_supplies[] = { + "vdda-0p9", + "vdda-1p2" +}; + +static const char * const x1e_genpd_names[] = { + "mx", + "mmcx", +}; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { + .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0, + .reg_info = { + .init_seq = lane_regs_x1e80100, + .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), + .common_regs_offset = 0x1000, + }, + .supply_names = (const char **)x1e_supplies, + .num_supplies = ARRAY_SIZE(x1e_supplies), + .clk_names = (const char **)x1e_clks, + .num_clk = ARRAY_SIZE(x1e_clks), + .opp_clk = x1e_clks[0], + .timer_clk = x1e_clks[1], + .genpd_names = (const char **)x1e_genpd_names, + .num_genpd_names = ARRAY_SIZE(x1e_genpd_names), +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c new file mode 100644 index 0000000000000..47acf0d586a15 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "phy-qcom-mipi-csi2.h" + +static int +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, + s64 link_freq) +{ + struct device *dev = csi2phy->dev; + unsigned long opp_rate = link_freq / 4; + struct dev_pm_opp *opp; + long timer_rate; + int ret; + + opp = dev_pm_opp_find_freq_ceil(dev, &opp_rate); + if (IS_ERR(opp)) { + dev_err(csi2phy->dev, "Couldn't find ceiling for %lld Hz\n", + link_freq); + return PTR_ERR(opp); + } + + for (int i = 0; i < csi2phy->num_pds; i++) { + unsigned int perf = dev_pm_opp_get_required_pstate(opp, i); + + ret = dev_pm_genpd_set_performance_state(csi2phy->pds[i], perf); + if (ret) { + dev_err(csi2phy->dev, "Couldn't set perf state %u\n", + perf); + dev_pm_opp_put(opp); + return ret; + } + } + dev_pm_opp_put(opp); + + ret = dev_pm_opp_set_rate(dev, opp_rate); + if (ret) { + dev_err(csi2phy->dev, "dev_pm_opp_set_rate() fail\n"); + return ret; + } + + timer_rate = clk_round_rate(csi2phy->timer_clk, link_freq / 4); + if (timer_rate < 0) + return timer_rate; + + ret = clk_set_rate(csi2phy->timer_clk, timer_rate); + if (ret) + return ret; + + csi2phy->timer_clk_rate = timer_rate; + + return 0; +} + +static int phy_qcom_mipi_csi2_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy; + struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg; + int ret; + int i; + + ret = phy_mipi_dphy_config_validate(dphy_cfg); + if (ret) + return ret; + + if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES) + return -EINVAL; + + stream_cfg->link_freq = dphy_cfg->hs_clk_rate; + stream_cfg->num_data_lanes = dphy_cfg->lanes; + + for (i = 0; i < stream_cfg->num_data_lanes; i++) { + stream_cfg->lane_cfg.data[i].pol = dphy_cfg->lane_polarities[i]; + stream_cfg->lane_cfg.data[i].pos = dphy_cfg->lane_positions[i]; + } + + stream_cfg->lane_cfg.clk.pol = dphy_cfg->clock_lane_polarity; + stream_cfg->lane_cfg.clk.pos = dphy_cfg->clock_lane_position; + + return 0; +} + +static int phy_qcom_mipi_csi2_power_on(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops; + struct device *dev = &phy->dev; + int ret; + + ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + if (ret) + return ret; + + ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq); + if (ret) + goto poweroff_phy; + + ret = clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + if (ret) { + dev_err(dev, "failed to enable clocks, %d\n", ret); + goto poweroff_phy; + } + + ops->reset(csi2phy); + + ops->hw_version_read(csi2phy); + + return ops->lanes_enable(csi2phy, &csi2phy->stream_cfg); + +poweroff_phy: + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return ret; +} + +static int phy_qcom_mipi_csi2_power_off(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + int i; + + for (i = 0; i < csi2phy->num_pds; i++) + dev_pm_genpd_set_performance_state(csi2phy->pds[i], 0); + + clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return 0; +} + +static const struct phy_ops phy_qcom_mipi_csi2_ops = { + .configure = phy_qcom_mipi_csi2_configure, + .power_on = phy_qcom_mipi_csi2_power_on, + .power_off = phy_qcom_mipi_csi2_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *qcom_csi2_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct mipi_csi2phy_device *csi2phy = dev_get_drvdata(dev); + + if (args->args[0] != PHY_QCOM_CSI2_MODE_DPHY) { + dev_err(csi2phy->dev, "mode %d -EOPNOTSUPP\n", args->args[0]); + return ERR_PTR(-EOPNOTSUPP); + } + + csi2phy->phy_mode = args->args[0]; + + return csi2phy->phy; +} + +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) +{ + unsigned int i, num_clk, num_supplies, num_pds; + struct mipi_csi2phy_device *csi2phy; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *generic_phy; + int ret; + + csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); + if (!csi2phy) + return -ENOMEM; + + csi2phy->dev = dev; + dev_set_drvdata(dev, csi2phy); + + csi2phy->soc_cfg = device_get_match_data(&pdev->dev); + + if (!csi2phy->soc_cfg) + return -EINVAL; + + num_clk = csi2phy->soc_cfg->num_clk; + csi2phy->clks = devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP_KERNEL); + if (!csi2phy->clks) + return -ENOMEM; + + num_pds = csi2phy->soc_cfg->num_genpd_names; + if (!num_pds) + return -EINVAL; + + csi2phy->pds = devm_kzalloc(dev, sizeof(*csi2phy->pds) * num_pds, GFP_KERNEL); + if (!csi2phy->pds) + return -ENOMEM; + + for (i = 0; i < num_pds; i++) { + csi2phy->pds[i] = dev_pm_domain_attach_by_name(dev, + csi2phy->soc_cfg->genpd_names[i]); + if (IS_ERR(csi2phy->pds[i])) { + return dev_err_probe(dev, PTR_ERR(csi2phy->pds[i]), + "Failed to attach %s\n", + csi2phy->soc_cfg->genpd_names[i]); + } + } + csi2phy->num_pds = num_pds; + + for (i = 0; i < num_clk; i++) + csi2phy->clks[i].id = csi2phy->soc_cfg->clk_names[i]; + + ret = devm_clk_bulk_get(dev, num_clk, csi2phy->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + csi2phy->timer_clk = devm_clk_get(dev, csi2phy->soc_cfg->timer_clk); + if (IS_ERR(csi2phy->timer_clk)) { + return dev_err_probe(dev, PTR_ERR(csi2phy->timer_clk), + "Failed to get timer clock\n"); + } + + ret = devm_pm_opp_set_clkname(dev, csi2phy->soc_cfg->opp_clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to set opp clkname\n"); + + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + num_supplies = csi2phy->soc_cfg->num_supplies; + csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies, + GFP_KERNEL); + if (!csi2phy->supplies) + return -ENOMEM; + + for (i = 0; i < num_supplies; i++) + csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i]; + + ret = devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); + + csi2phy->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi2phy->base)) + return PTR_ERR(csi2phy->base); + + generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + return dev_err_probe(dev, ret, "failed to create phy\n"); + } + csi2phy->phy = generic_phy; + + phy_set_drvdata(generic_phy, csi2phy); + + phy_provider = devm_of_phy_provider_register(dev, qcom_csi2_phy_xlate); + if (!IS_ERR(phy_provider)) + dev_dbg(dev, "Registered MIPI CSI2 PHY device\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = { + { .compatible = "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e }, + { } +}; +MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); + +static struct platform_driver phy_qcom_mipi_csi2_driver = { + .probe = phy_qcom_mipi_csi2_probe, + .driver = { + .name = "qcom-mipi-csi2-phy", + .of_match_table = phy_qcom_mipi_csi2_of_match_table, + }, +}; + +module_platform_driver(phy_qcom_mipi_csi2_driver); + +MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver"); +MODULE_AUTHOR("Bryan O'Donoghue "); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..27607dea412f1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * + * Qualcomm MIPI CSI2 CPHY/DPHY driver + * + * Copyright (C) 2025 Linaro Ltd. + */ +#ifndef __PHY_QCOM_MIPI_CSI2_H__ +#define __PHY_QCOM_MIPI_CSI2_H__ + +#include + +#define CSI2_MAX_DATA_LANES 4 + +struct mipi_csi2phy_lane { + u8 pos; + u8 pol; +}; + +struct mipi_csi2phy_lanes_cfg { + struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES]; + struct mipi_csi2phy_lane clk; +}; + +struct mipi_csi2phy_stream_cfg { + s64 link_freq; + u8 num_data_lanes; + struct mipi_csi2phy_lanes_cfg lane_cfg; +}; + +struct mipi_csi2phy_device; + +struct mipi_csi2phy_hw_ops { + void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev); + void (*reset)(struct mipi_csi2phy_device *csi2phy_dev); + int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); + void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); +}; + +struct mipi_csi2phy_lane_regs { + const s32 reg_addr; + const s32 reg_data; + const u32 delay_us; + const u32 param_type; +}; + +struct mipi_csi2phy_device_regs { + const struct mipi_csi2phy_lane_regs *init_seq; + const int lane_array_size; + const u32 common_regs_offset; +}; + +struct mipi_csi2phy_soc_cfg { + const struct mipi_csi2phy_hw_ops *ops; + const struct mipi_csi2phy_device_regs reg_info; + + const char ** const supply_names; + const unsigned int num_supplies; + + const char ** const clk_names; + const unsigned int num_clk; + + const char * const opp_clk; + const char * const timer_clk; + + const char ** const genpd_names; + const unsigned int num_genpd_names; +}; + +struct mipi_csi2phy_device { + struct device *dev; + u8 phy_mode; + + struct phy *phy; + void __iomem *base; + + struct clk_bulk_data *clks; + struct clk *timer_clk; + u32 timer_clk_rate; + + struct regulator_bulk_data *supplies; + struct device **pds; + unsigned int num_pds; + + const struct mipi_csi2phy_soc_cfg *soc_cfg; + struct mipi_csi2phy_stream_cfg stream_cfg; + + u32 hw_version; +}; + +extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; + +#endif /* __PHY_QCOM_MIPI_CSI2_H__ */ From 639b61ee67955902d20eb59722c5d7b29eac70d9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:29 +0000 Subject: [PATCH 0098/1058] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add optional PHY handle definitions Add optional PHY handle definitions. This will allow for supporting both legacy PHY definitions as well as supporting the optional new handle based approach. Drop the legacy high-level 0p8 and 1p2 supplies as required, each PHY has its own individual rails. The old binding is still valid but with individual nodes we define the rails in the CSIPHY sub-nodes. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-1-5b93415be6dd@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 2d1662ef522b7..c17b9757b2c86 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -39,6 +39,14 @@ properties: - const: vfe_lite0 - const: vfe_lite1 + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + clocks: maxItems: 29 @@ -126,6 +134,16 @@ properties: description: 1.2V supply to a PHY. + phys: + maxItems: 4 + + phy-names: + items: + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy4 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -158,6 +176,14 @@ properties: required: - data-lanes +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + required: - compatible - reg @@ -171,8 +197,6 @@ required: - iommus - power-domains - power-domain-names - - vdd-csiphy-0p8-supply - - vdd-csiphy-1p2-supply - ports additionalProperties: false @@ -184,6 +208,7 @@ examples: #include #include #include + #include #include soc { @@ -229,6 +254,10 @@ examples: "vfe_lite0", "vfe_lite1"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, <&camcc CAM_CC_CORE_AHB_CLK>, From 771b168b10d2c4df8873924623975ecc73429327 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:30 +0000 Subject: [PATCH 0099/1058] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add support for combo-mode endpoints Qualcomm CSI2 PHYs support a mode where two sensors may be attached to the one CSIPHY. When we have one endpoint we may have - DPHY 1, 2 or 4 data lanes + 1 clock lane - CPHY 3 wire data lane When we have two endpoints this indicates the special fixed combo-mode. - DPHY endpoint0 => 2+1 and endpoint1 => 1+1 data-lane/clock-lane combination. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-2-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index c17b9757b2c86..f44138f522bba 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -148,7 +148,8 @@ properties: $ref: /schemas/graph.yaml#/properties/ports description: - CSI input ports. + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. patternProperties: "^port@[0-3]$": @@ -156,26 +157,86 @@ properties: unevaluatedProperties: false description: - Input port for receiving CSI data from a CSIPHY. + Input port for receiving CSI data. properties: - endpoint: + endpoint@0: $ref: video-interfaces.yaml# unevaluatedProperties: false + description: + Endpoint for receiving a single sensor input (or first leg of combo). + properties: data-lanes: minItems: 1 - maxItems: 4 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 bus-type: enum: - 1 # MEDIA_BUS_TYPE_CSI2_CPHY - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + required: - data-lanes + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + patternProperties: "^phy@[0-9a-f]+$": $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml From f3cb7b9e0b65b014e1ba492854cbc5622aed55b8 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:31 +0000 Subject: [PATCH 0100/1058] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Describe iommu entries The original iommus list included entries for ICP and BPS/IPE S1 contexts. Only the five S1 HLOS stream IDs are required by the CAMSS ISP hardware: IFE/IFE_LITE read and write, SFE read and write, and CDM IFE. The remaining entries serve other hardware blocks which will be described in their own nodes as support is added. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-3-5b93415be6dd@linaro.org/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index f44138f522bba..d2763977a494d 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -112,7 +112,22 @@ properties: - const: sf_icp_mnoc iommus: - maxItems: 8 + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected power-domains: items: @@ -422,13 +437,10 @@ examples: "sf_icp_mnoc"; iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, <&apps_smmu 0x860 0x60>, - <&apps_smmu 0x1800 0x60>, - <&apps_smmu 0x1860 0x60>, - <&apps_smmu 0x18e0 0x00>, - <&apps_smmu 0x1980 0x20>, - <&apps_smmu 0x1900 0x00>, - <&apps_smmu 0x19a0 0x20>; + <&apps_smmu 0x18a0 0x0>; power-domains = <&camcc CAM_CC_IFE_0_GDSC>, <&camcc CAM_CC_IFE_1_GDSC>, From 2c33cb0ab5cb46fc98de60fb57c5eb86c731c465 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:32 +0000 Subject: [PATCH 0101/1058] FROMLIST: media: qcom: camss: Add support to populate sub-devices Use devm_of_platform_populate() to populate subs in the tree. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-4-5b93415be6dd@linaro.org/ Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2123f6388e3d7..95e655a8b6aa0 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -5362,6 +5363,8 @@ static int camss_probe(struct platform_device *pdev) if (!camss) return -ENOMEM; + devm_of_platform_populate(dev); + camss->res = of_device_get_match_data(dev); atomic_set(&camss->ref_count, 0); From 7666093618d42df4fef7f9e238685c5354ce5f20 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:33 +0000 Subject: [PATCH 0102/1058] FROMLIST: media: qcom: camss: Add legacy_phy flag to SoC definition structures Flag which SoCs have legacy - builtin PHY code. This will be useful in subsequent patches to inform PHY bringup logic if legacy bindings are available. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-5-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 17 +++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 95e655a8b6aa0..e814a96953b1b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5512,6 +5512,7 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, + .legacy_phy = true, .csiphy_res = csiphy_res_8x16, .csid_res = csid_res_8x16, .ispif_res = &ispif_res_8x16, @@ -5523,6 +5524,7 @@ static const struct camss_resources msm8916_resources = { static const struct camss_resources msm8939_resources = { .version = CAMSS_8x39, + .legacy_phy = true, .csiphy_res = csiphy_res_8x39, .csid_res = csid_res_8x39, .ispif_res = &ispif_res_8x39, @@ -5534,6 +5536,7 @@ static const struct camss_resources msm8939_resources = { static const struct camss_resources msm8953_resources = { .version = CAMSS_8x53, + .legacy_phy = true, .icc_res = icc_res_8x53, .icc_path_num = ARRAY_SIZE(icc_res_8x53), .csiphy_res = csiphy_res_8x96, @@ -5547,6 +5550,7 @@ static const struct camss_resources msm8953_resources = { static const struct camss_resources msm8996_resources = { .version = CAMSS_8x96, + .legacy_phy = true, .csiphy_res = csiphy_res_8x96, .csid_res = csid_res_8x96, .ispif_res = &ispif_res_8x96, @@ -5558,6 +5562,7 @@ static const struct camss_resources msm8996_resources = { static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, + .legacy_phy = true, .csiphy_res = csiphy_res_2290, .csid_res = csid_res_2290, .vfe_res = vfe_res_2290, @@ -5571,6 +5576,7 @@ static const struct camss_resources qcm2290_resources = { static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8300, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5587,6 +5593,7 @@ static const struct camss_resources qcs8300_resources = { static const struct camss_resources sa8775p_resources = { .version = CAMSS_8775P, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8775p, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5602,6 +5609,7 @@ static const struct camss_resources sa8775p_resources = { static const struct camss_resources sdm660_resources = { .version = CAMSS_660, + .legacy_phy = true, .csiphy_res = csiphy_res_660, .csid_res = csid_res_660, .ispif_res = &ispif_res_660, @@ -5613,6 +5621,7 @@ static const struct camss_resources sdm660_resources = { static const struct camss_resources sdm670_resources = { .version = CAMSS_845, + .legacy_phy = true, .csiphy_res = csiphy_res_670, .csid_res = csid_res_670, .vfe_res = vfe_res_670, @@ -5624,6 +5633,7 @@ static const struct camss_resources sdm670_resources = { static const struct camss_resources sdm845_resources = { .version = CAMSS_845, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_845, .csid_res = csid_res_845, .vfe_res = vfe_res_845, @@ -5635,6 +5645,7 @@ static const struct camss_resources sdm845_resources = { static const struct camss_resources sm6150_resources = { .version = CAMSS_6150, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm6150, .csid_res = csid_res_sm6150, .vfe_res = vfe_res_sm6150, @@ -5661,6 +5672,7 @@ static const struct camss_resources sm6350_resources = { static const struct camss_resources sm8250_resources = { .version = CAMSS_8250, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8250, .csid_res = csid_res_8250, .vfe_res = vfe_res_8250, @@ -5674,6 +5686,7 @@ static const struct camss_resources sm8250_resources = { static const struct camss_resources sc8280xp_resources = { .version = CAMSS_8280XP, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sc8280xp, .csid_res = csid_res_sc8280xp, .ispif_res = NULL, @@ -5688,6 +5701,7 @@ static const struct camss_resources sc8280xp_resources = { static const struct camss_resources sc7280_resources = { .version = CAMSS_7280, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_7280, .csid_res = csid_res_7280, .vfe_res = vfe_res_7280, @@ -5701,6 +5715,7 @@ static const struct camss_resources sc7280_resources = { static const struct camss_resources sm8550_resources = { .version = CAMSS_8550, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8550, .csid_res = csid_res_8550, .vfe_res = vfe_res_8550, @@ -5715,6 +5730,7 @@ static const struct camss_resources sm8550_resources = { static const struct camss_resources sm8650_resources = { .version = CAMSS_8650, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm8650, .csid_res = csid_res_sm8650, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5729,6 +5745,7 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .tpg_res = tpg_res_x1e80100, .csid_res = csid_res_x1e80100, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 93d691c8ac63b..698694d3064ea 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -107,6 +107,7 @@ enum icc_count { struct camss_resources { enum camss_version version; const char *pd_name; + const bool legacy_phy; const struct camss_subdev_resources *csiphy_res; const struct camss_subdev_resources *tpg_res; const struct camss_subdev_resources *csid_res; From 8b37333bd4ea6ff1f1970b185ce036257d1876c6 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:34 +0000 Subject: [PATCH 0103/1058] FROMLIST: media: qcom: camss: Add support for PHY API devices Add the ability to use a PHY pointer which interacts with the standard PHY API. In the first instance the code will try to use the new PHY interface. If no PHYs are present in the DT then the legacy method will be attempted. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-6-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue --- drivers/media/platform/qcom/camss/Kconfig | 1 + .../media/platform/qcom/camss/camss-csiphy.c | 189 ++++++++++++++++-- .../media/platform/qcom/camss/camss-csiphy.h | 7 + drivers/media/platform/qcom/camss/camss.c | 72 +++++-- 4 files changed, 239 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig index 4eda48cb1adf0..1edc5e5a1829e 100644 --- a/drivers/media/platform/qcom/camss/Kconfig +++ b/drivers/media/platform/qcom/camss/Kconfig @@ -7,3 +7,4 @@ config VIDEO_QCOM_CAMSS select VIDEO_V4L2_SUBDEV_API select VIDEOBUF2_DMA_SG select V4L2_FWNODE + select PHY_QCOM_MIPI_CSI2 diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 539ac4888b608..57bc0eda43a18 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -7,12 +7,14 @@ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. * Copyright (C) 2016-2018 Linaro Ltd. */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -131,10 +133,10 @@ static u8 csiphy_get_bpp(const struct csiphy_format_info *formats, } /* - * csiphy_set_clock_rates - Calculate and set clock rates on CSIPHY module + * csiphy_set_clock_rates_legacy - Calculate and set clock rates on CSIPHY module * @csiphy: CSIPHY device */ -static int csiphy_set_clock_rates(struct csiphy_device *csiphy) +static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) { struct device *dev = csiphy->camss->dev; s64 link_freq; @@ -200,7 +202,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_set_power(struct v4l2_subdev *sd, int on) +static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct device *dev = csiphy->camss->dev; @@ -219,7 +221,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) return ret; } - ret = csiphy_set_clock_rates(csiphy); + ret = csiphy_set_clock_rates_legacy(csiphy); if (ret < 0) { regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies); @@ -254,7 +256,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) } /* - * csiphy_stream_on - Enable streaming on CSIPHY module + * csiphy_stream_on_legacy - Enable streaming on CSIPHY module * @csiphy: CSIPHY device * * Helper function to enable streaming on CSIPHY module. @@ -262,7 +264,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_stream_on(struct csiphy_device *csiphy) +static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) { struct csiphy_config *cfg = &csiphy->cfg; s64 link_freq; @@ -306,11 +308,99 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) * * Helper function to disable streaming on CSIPHY module */ -static void csiphy_stream_off(struct csiphy_device *csiphy) +static void csiphy_stream_off_legacy(struct csiphy_device *csiphy) { csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); } +/* + * csiphy_stream_on - Enable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to enable streaming on CSIPHY module. + * Main configuration of CSIPHY module is also done here. + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_stream_on(struct csiphy_device *csiphy) +{ + u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, + csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); + struct csiphy_lanes_cfg *lncfg = &csiphy->cfg.csi2->lane_cfg; + struct phy_configure_opts_mipi_dphy *dphy_cfg; + union phy_configure_opts dphy_opts = { 0 }; + struct device *dev = csiphy->camss->dev; + u8 num_lanes = lncfg->num_data; + s64 link_freq; + int i; + int ret; + + dphy_cfg = &dphy_opts.mipi_dphy; + + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + + if (link_freq < 0) { + dev_err(dev, + "Cannot get CSI2 transmitter's link frequency\n"); + return -EINVAL; + } + + phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes, dphy_cfg); + + /* Set clock lane id and polarity */ + dphy_cfg->clock_lane_position = lncfg->clk.pos; + dphy_cfg->clock_lane_polarity = lncfg->clk.pol; + + /* Set data lane_mask and lane_polarities */ + for (i = 0; i < num_lanes; i++) { + dphy_cfg->lane_positions[i] = lncfg->data[i].pos; + dphy_cfg->lane_polarities[i] = lncfg->data[i].pol; + } + + phy_set_mode(csiphy->phy, PHY_MODE_MIPI_DPHY); + + ret = phy_configure(csiphy->phy, &dphy_opts); + if (ret) { + dev_err(dev, "failed to configure MIPI D-PHY\n"); + goto error; + } + + return phy_power_on(csiphy->phy); + +error: + return ret; +} + +/* + * csiphy_stream_off - Disable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to disable streaming on CSIPHY module + */ +static void csiphy_stream_off(struct csiphy_device *csiphy) +{ + phy_power_off(csiphy->phy); +} + +/* + * csiphy_set_stream - Enable/disable streaming on CSIPHY module + * @sd: CSIPHY V4L2 subdevice + * @enable: Requested streaming state + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_set_stream_legacy(struct v4l2_subdev *sd, int enable) +{ + struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); + int ret = 0; + + if (enable) + ret = csiphy_stream_on_legacy(csiphy); + else + csiphy_stream_off_legacy(csiphy); + + return ret; +} /* * csiphy_set_stream - Enable/disable streaming on CSIPHY module @@ -572,16 +662,16 @@ csiphy_match_clock_name(const char *clock_name, const char *format, ...) } /* - * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * msm_csiphy_subdev_init_legacy - Initialize CSIPHY device structure and resources * @csiphy: CSIPHY device * @res: CSIPHY module resources table * @id: CSIPHY module id * * Return 0 on success or a negative error code otherwise */ -int msm_csiphy_subdev_init(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id) +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) { struct device *dev = camss->dev; struct platform_device *pdev = to_platform_device(dev); @@ -709,6 +799,60 @@ int msm_csiphy_subdev_init(struct camss *camss, return ret; } +/* + * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * @csiphy: CSIPHY device + * @res: CSIPHY module resources table + * @id: CSIPHY module id + * + * Return 0 on success or a negative error code otherwise + */ +int msm_csiphy_subdev_init(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) +{ + struct device *dev = camss->dev; + struct of_phandle_args args; + int idx; + int ret; + + snprintf(csiphy->name, ARRAY_SIZE(csiphy->name), "csiphy%d", id); + + idx = of_property_match_string(dev->of_node, "phy-names", csiphy->name); + if (idx < 0) { + dev_err(dev, "%s not found\n", csiphy->name); + return idx; + } + + ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", idx, &args); + if (ret < 0) { + dev_err(dev, "unable to parse phys args %s\n", csiphy->name); + return ret; + } + + if (!of_device_is_available(args.np)) + goto put_np; + + csiphy->phy = devm_phy_get(dev, csiphy->name); + if (IS_ERR(csiphy->phy)) { + ret = PTR_ERR(csiphy->phy); + goto put_np; + } + + csiphy->camss = camss; + csiphy->id = id; + csiphy->res = &res->csiphy; + + ret = phy_init(csiphy->phy); + if (ret) + dev_err(dev, "phy %s init fail %d\n", csiphy->name, ret); + +put_np: + of_node_put(args.np); + + return ret; +} + /* * csiphy_link_setup - Setup CSIPHY connections * @entity: Pointer to media entity structure @@ -743,8 +887,12 @@ static int csiphy_link_setup(struct media_entity *entity, return 0; } -static const struct v4l2_subdev_core_ops csiphy_core_ops = { - .s_power = csiphy_set_power, +static const struct v4l2_subdev_core_ops csiphy_core_ops_legacy = { + .s_power = csiphy_set_power_legacy, +}; + +static const struct v4l2_subdev_video_ops csiphy_video_ops_legacy = { + .s_stream = csiphy_set_stream_legacy, }; static const struct v4l2_subdev_video_ops csiphy_video_ops = { @@ -758,8 +906,13 @@ static const struct v4l2_subdev_pad_ops csiphy_pad_ops = { .set_fmt = csiphy_set_format, }; +static const struct v4l2_subdev_ops csiphy_v4l2_ops_legacy = { + .core = &csiphy_core_ops_legacy, + .video = &csiphy_video_ops_legacy, + .pad = &csiphy_pad_ops, +}; + static const struct v4l2_subdev_ops csiphy_v4l2_ops = { - .core = &csiphy_core_ops, .video = &csiphy_video_ops, .pad = &csiphy_pad_ops, }; @@ -788,7 +941,11 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, struct device *dev = csiphy->camss->dev; int ret; - v4l2_subdev_init(sd, &csiphy_v4l2_ops); + if (IS_ERR(csiphy->phy)) + v4l2_subdev_init(sd, &csiphy_v4l2_ops_legacy); + else + v4l2_subdev_init(sd, &csiphy_v4l2_ops); + sd->internal_ops = &csiphy_v4l2_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", @@ -828,6 +985,8 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, */ void msm_csiphy_unregister_entity(struct csiphy_device *csiphy) { + if (!IS_ERR(csiphy->phy)) + phy_exit(csiphy->phy); v4l2_device_unregister_subdev(&csiphy->subdev); media_entity_cleanup(&csiphy->subdev.entity); } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 9d9657b82f748..1879826034aac 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -97,6 +98,7 @@ struct csiphy_device_regs { struct csiphy_device { struct camss *camss; + struct phy *phy; u8 id; struct v4l2_subdev subdev; struct media_pad pads[MSM_CSIPHY_PADS_NUM]; @@ -104,6 +106,7 @@ struct csiphy_device { void __iomem *base_clk_mux; u32 irq; char irq_name[30]; + char name[16]; struct camss_clock *clock; bool *rate_set; int nclocks; @@ -118,6 +121,10 @@ struct csiphy_device { struct camss_subdev_resources; +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id); + int msm_csiphy_subdev_init(struct camss *camss, struct csiphy_device *csiphy, const struct camss_subdev_resources *res, u8 id); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e814a96953b1b..bc268148b57db 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4794,14 +4794,35 @@ static int camss_parse_endpoint_node(struct device *dev, static int camss_parse_ports(struct camss *camss) { struct device *dev = camss->dev; + const struct camss_resources *res = camss->res; struct fwnode_handle *fwnode = dev_fwnode(dev), *ep; int ret; fwnode_graph_for_each_endpoint(fwnode, ep) { struct camss_async_subdev *csd; + struct fwnode_handle *remote; + + if (!fwnode_device_is_available(ep)) + continue; + + if (res->legacy_phy) { + csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, + typeof(*csd)); + } else { + /* + * For non-legacy PHY, the CSIPHY is a separate device. + * Register the remote endpoint (CSIPHY's endpoint) as + * the async subdev, not the remote port parent. + */ + remote = fwnode_graph_get_remote_endpoint(ep); + if (!remote) + continue; + + csd = v4l2_async_nf_add_fwnode(&camss->notifier, remote, + struct camss_async_subdev); + fwnode_handle_put(remote); + } - csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, - typeof(*csd)); if (IS_ERR(csd)) { ret = PTR_ERR(csd); goto err_cleanup; @@ -4833,15 +4854,26 @@ static int camss_init_subdevices(struct camss *camss) unsigned int i; int ret; - for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], - &res->csiphy_res[i], - res->csiphy_res[i].csiphy.id); - if (ret < 0) { - dev_err(camss->dev, - "Failed to init csiphy%d sub-device: %d\n", - i, ret); - return ret; + if (!res->legacy_phy) { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) + return ret; + } + } else { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init_legacy(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) { + dev_err(camss->dev, + "Failed to init csiphy%d sub-device: %d\n", + i, ret); + return ret; + } + camss->csiphy[i].phy = ERR_PTR(-ENODEV); } } @@ -4931,6 +4963,9 @@ static int camss_link_entities(struct camss *camss) for (i = 0; i < camss->res->csiphy_num; i++) { for (j = 0; j < camss->res->csid_num; j++) { + if (!camss->csiphy[i].phy) + continue; + ret = media_create_pad_link(&camss->csiphy[i].subdev.entity, MSM_CSIPHY_PAD_SRC, &camss->csid[j].subdev.entity, @@ -5057,6 +5092,9 @@ static int camss_register_entities(struct camss *camss) int ret; for (i = 0; i < camss->res->csiphy_num; i++) { + if (!camss->csiphy[i].phy) + continue; + ret = msm_csiphy_register_entity(&camss->csiphy[i], &camss->v4l2_dev); if (ret < 0) { @@ -5132,8 +5170,10 @@ static int camss_register_entities(struct camss *camss) i = camss->res->csiphy_num; err_reg_csiphy: - for (i--; i >= 0; i--) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i--; i >= 0; i--) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } return ret; } @@ -5148,8 +5188,10 @@ static void camss_unregister_entities(struct camss *camss) { unsigned int i; - for (i = 0; i < camss->res->csiphy_num; i++) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i = 0; i < camss->res->csiphy_num; i++) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } if (camss->tpg) { for (i = 0; i < camss->res->tpg_num; i++) From 6f807b7424b0066d7a1b11f390c140ab441311d4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:35 +0000 Subject: [PATCH 0104/1058] FROMLIST: media: qcom: camss: Drop legacy PHY descriptions from x1e x1e is the first CAMSS SoC to use the new PHY interface. Drop the redundant legacy CSIPHY descriptions. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-7-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 37 ----------------------- 1 file changed, 37 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index bc268148b57db..36918e9c22eb1 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4191,15 +4191,6 @@ static const struct resources_icc icc_res_sa8775p[] = { static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy0" }, - .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4208,15 +4199,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY1 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy1" }, - .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4225,15 +4207,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY2 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy2" }, - .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4242,15 +4215,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY4 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, .csiphy = { .id = 4, .hw_ops = &csiphy_ops_3ph_1_0, @@ -5787,7 +5751,6 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .tpg_res = tpg_res_x1e80100, .csid_res = csid_res_x1e80100, From 39caf36fdd99c3d877bea225048477ed529f9c5a Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:13 -0700 Subject: [PATCH 0105/1058] FROMLIST: media: dt-bindings: Add CAMSS device for Kaanapali Add bindings for Camera Subsystem (CAMSS) on the Qualcomm Kaanapali platform. The Kaanapali platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-1-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Reviewed-by: Krzysztof Kozlowski Signed-off-by: Hangxiang Ma --- .../bindings/media/qcom,kaanapali-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml new file mode 100644 index 0000000000000..2f2bb682f32f4 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,kaanapali-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,kaanapali-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x9000>, + <0x0 0x092f0000 0x0 0x9000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p8-supply = <&vreg_0p8_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 06cced3caf6ce2c8e4a58eef43e7ec1bf3145ee2 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:14 -0700 Subject: [PATCH 0106/1058] FROMLIST: media: qcom: camss: Add Kaanapali compatible camss driver Add support for Kaanapali in the camss driver. Add high level resource information along with the bus bandwidth votes. Module level detailed resource information will be enumerated in the following patches of the series. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-2-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 36918e9c22eb1..c6754760dc45b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -35,6 +35,20 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct resources_icc icc_res_kaanapali[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_8x16[] = { /* CSIPHY0 */ { @@ -5516,6 +5530,13 @@ static void camss_remove(struct platform_device *pdev) camss_genpd_cleanup(camss); } +static const struct camss_resources kaanapali_resources = { + .version = CAMSS_KAANAPALI, + .pd_name = "top", + .icc_res = icc_res_kaanapali, + .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), +}; + static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, .legacy_phy = true, @@ -5765,6 +5786,7 @@ static const struct camss_resources x1e80100_resources = { }; static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 698694d3064ea..cea213dc36ebc 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -96,6 +96,7 @@ enum camss_version { CAMSS_8550, CAMSS_8650, CAMSS_8775P, + CAMSS_KAANAPALI, CAMSS_X1E80100, }; From 61b8fe70e37dd0284eccc88885492fad0b244b07 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:15 -0700 Subject: [PATCH 0107/1058] FROMLIST: media: qcom: camss: csiphy: Add support for v2.4.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.4.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-3-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 124 +++++++++++++++++ drivers/media/platform/qcom/camss/camss.c | 125 ++++++++++++++++++ 2 files changed, 249 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index dac8d2ecf7995..795b333185e54 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -804,6 +804,123 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_2_4_0[] = { + /* LN 0 */ + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x005C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 2 */ + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x045C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 4 */ + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x085C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 6 */ + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C38, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x0C5C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0C60, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN CLK */ + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_x1e80100[] = { @@ -1140,6 +1257,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: ret = true; break; @@ -1259,6 +1377,12 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_KAANAPALI: + regs->lane_regs = &lane_regs_2_4_0[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); + regs->offset = 0x1000; + regs->common_status_offset = 0x138; + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c6754760dc45b..27e1ad7ed799a 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -35,6 +35,129 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct camss_subdev_resources csiphy_res_kaanapali[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5533,8 +5656,10 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources kaanapali_resources = { .version = CAMSS_KAANAPALI, .pd_name = "top", + .csiphy_res = csiphy_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), + .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From dba6e2bd8117442c16b3dcf3454d0a26c3fcdbe8 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:16 -0700 Subject: [PATCH 0108/1058] FROMLIST: media: qcom: camss: csid: Add support for CSID gen4 Add more detailed resource information for CSID devices along with the driver for CSID gen4 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. And aggregate a common definition 'CSI2_RX_CFG0_PHY_SEL_BASE_IDX' into csid header file. In this CSID version, RUP and AUP update values are split into two registers along with a SET register. Accordingly, enhance the CSID interface to accommodate both the legacy combined reg_update and the split RUP and AUP updates. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-4-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-680.c | 1 - .../platform/qcom/camss/camss-csid-gen3.c | 1 - .../platform/qcom/camss/camss-csid-gen4.c | 376 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 11 +- drivers/media/platform/qcom/camss/camss.c | 75 ++++ 6 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 27898b3cc7d3c..cebfd947f28ef 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -10,6 +10,7 @@ qcom-camss-objs += \ camss-csid-680.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ + camss-csid-gen4.o \ camss-csiphy.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-680.c b/drivers/media/platform/qcom/camss/camss-csid-680.c index 345a67c8fb947..bf7164085ddb4 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-680.c +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c @@ -101,7 +101,6 @@ #define CSI2_RX_CFG0_DL2_INPUT_SEL 12 #define CSI2_RX_CFG0_DL3_INPUT_SEL 16 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSI2_RX_CFG0_PHY_TYPE_SEL 24 #define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) #define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 0fdbf75fb27db..da9458cd178bd 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -105,7 +105,6 @@ #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ (0x34C + 0x100 * (rdi)) :\ (0x54C + 0x100 * (rdi))) -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen4.c b/drivers/media/platform/qcom/camss/camss-csid-gen4.c new file mode 100644 index 0000000000000..41035352c4bb0 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-gen4.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-gen4.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0x108 +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10C +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x110 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x114 +#define CSID_AUP_CMD 0x118 +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x11C +#define RUP_SET BIT(0) +#define MUP BIT(4) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS 0x180 +#define CSID_TOP_IRQ_MASK 0x184 +#define CSID_TOP_IRQ_CLEAR 0x188 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS 0x1A0 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0x1A4 +#define CSID_BUF_DONE_IRQ_CLEAR 0x1A8 +#define CSID_BUF_DONE_IRQ_SET 0x1AC + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS 0x1B0 +#define CSID_CSI2_RX_IRQ_MASK 0x1B4 +#define CSID_CSI2_RX_IRQ_CLEAR 0x1B8 +#define CSID_CSI2_RX_IRQ_SET 0x1BC + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 0x880 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 0x884 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_GEN4 (csid_is_lite(csid) ? 4 : 5) + +/* RDI Configuration */ +#define CSID_RDI_CFG0(rdi) \ + ((csid_is_lite(csid) ? 0x3080 : 0x5480) + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ((csid_is_lite(csid) ? 0x3088 : 0x5488) + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ((csid_is_lite(csid) ? 0x3094 : 0x5494) + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0x5498 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x224 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_MASK(rdi) (0x228 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x22C + (0x10 * (rdi))) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_reg_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + writel(val, csid->base + CSID_RDI_CFG0(port)); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + CSID_RDI_CFG1(port)); + + /* Configure pixel store using dedicated register in gen4 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + CSID_RDI_CTRL(port)); + + val = readl(csid->base + CSID_RDI_CFG0(port)); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + CSID_RDI_CFG0(port)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_reg_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -EIO; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_gen4 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac8..e6590b2bd8be5 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -27,6 +27,8 @@ /* CSID hardware can demultiplex up to 4 outputs */ #define MSM_CSID_MAX_SRC_STREAMS 4 +/* CSIPHY to hardware PHY selector mapping */ +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSID_RESET_TIMEOUT_MS 500 enum csid_testgen_mode { @@ -154,7 +156,13 @@ struct csid_device { void __iomem *base; u32 irq; char irq_name[30]; - u32 reg_update; + union { + u32 reg_update; + struct { + u32 rup_update; + u32 aup_update; + }; + }; struct camss_clock *clock; int nclocks; struct regulator_bulk_data *supplies; @@ -218,6 +226,7 @@ extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; +extern const struct csid_hw_ops csid_ops_gen4; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 27e1ad7ed799a..56dce0dd21688 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -158,6 +158,79 @@ static const struct camss_subdev_resources csiphy_res_kaanapali[] = { }, }; +static const struct camss_subdev_resources csid_res_kaanapali[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5657,9 +5730,11 @@ static const struct camss_resources kaanapali_resources = { .version = CAMSS_KAANAPALI, .pd_name = "top", .csiphy_res = csiphy_res_kaanapali, + .csid_res = csid_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), + .csid_num = ARRAY_SIZE(csid_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 24577e4f5a0e39736b3ce926d56f64b565a68b15 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:17 -0700 Subject: [PATCH 0109/1058] FROMLIST: media: qcom: camss: vfe: Add support for VFE gen4 Add Video Front End (VFE) version gen4 as found on the Kaanapali SoC. The FULL front end modules in Kaanapali camera subsystem are called TFEs (Thin Front End), however, retaining the name VFE at places to maintain consistency and avoid unnecessary code changes. This change limits the VFE output lines to 3 for now as constrained by the CAMSS driver framework. Kaanapali architecture requires for the REG_UPDATE and AUP_UPDATE to be issued after all of the CSID configuration has been done. Additionally, the number of AUP_UPDATEs should match the number of buffers enqueued to the write master while it's being enabled. Although the real time data from TFE goes through the RT_CAMNOC, we are required to enable both the camnoc_rt_axi and camnoc_nrt_axi clocks for the PDX_NOC, that follows both the RT and NRT NOCs in this architecture, to ensure that both of the latter are idle after reset. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-5-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-vfe-gen4.c | 197 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss-vfe.c | 9 +- drivers/media/platform/qcom/camss/camss-vfe.h | 2 + drivers/media/platform/qcom/camss/camss.c | 138 ++++++++++++ 5 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index cebfd947f28ef..b114ca37e36e2 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -28,6 +28,7 @@ qcom-camss-objs += \ camss-vfe-680.o \ camss-vfe-gen1.o \ camss-vfe-gen3.o \ + camss-vfe-gen4.o \ camss-vfe-vbif.o \ camss-video.o diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c new file mode 100644 index 0000000000000..d73d70898710a --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-vfe-gen4.c + * + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen4 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include + +#include "camss.h" +#include "camss-vfe.h" + +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +#define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) + +#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) + +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define WM_CFG_EN BIT(0) +#define WM_VIR_FRM_EN BIT(1) +#define WM_CFG_MODE BIT(16) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) + +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) + +/* VFE lite has no such registers */ +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) + +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) + +/* + * IFE write master client IDs + * + * VIDEO_FULL 0 + * VIDEO_DC4_Y 1 + * VIDEO_DC4_C 2 + * VIDEO_DC16_Y 3 + * VIDEO_DC16_C 4 + * DISPLAY_DS2_Y 5 + * DISPLAY_DS2_C 6 + * FD_Y 7 + * FD_C 8 + * PIXEL_RAW 9 + * STATS_AEC_BG 10 + * STATS_AEC_BHIST 11 + * STATS_TINTLESS_BG 12 + * STATS_AWB_BG 13 + * STATS_AWB_BFW 14 + * STATS_AF_BHIST 15 + * STATS_ALSC_BG 16 + * STATS_FLICKER_BAYERRS 17 + * STATS_TMC_BHIST 18 + * PDAF_0 19 + * PDAF_1 20 + * PDAF_2 21 + * PDAF_3 22 + * RDI0 23 + * RDI1 24 + * RDI2 25 + * RDI3 26 + * RDI4 27 + * + * IFE Lite write master client IDs + * + * RDI0 0 + * RDI1 1 + * RDI2 2 + * RDI3 3 + * GAMMA 4 + * STATES_BE 5 + */ +#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) + +static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = + &line->video_out.active_fmt.fmt.pix_mp; + + wm = RDI_WM(wm); + + /* no clock gating at bus input */ + writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + + writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); + + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), + vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); + writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, + vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); + writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + + /* no dropped frames, one irq per frame */ + if (!vfe_is_lite(vfe)) { + writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); + } + + writel(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); + + writel(1, vfe->base + VFE_BUS_WM_MMU_PREFETCH_CFG(wm)); + writel(0xFFFFFFFF, vfe->base + VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(wm)); + + writel(WM_CFG_EN | WM_CFG_MODE, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) +{ + wm = RDI_WM(wm); + writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, + struct vfe_line *line) +{ + wm = RDI_WM(wm); + writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, false); +} + +static inline void vfe_reg_update_clear(struct vfe_device *vfe, + enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, true); +} + +static const struct camss_video_ops vfe_video_ops_gen4 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_gen4; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + vfe_isr_reset_ack(vfe); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + /* nop */ + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +const struct vfe_hw_ops vfe_ops_gen4 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 319d191589884..826ab85a44a14 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -353,6 +353,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: @@ -525,7 +526,8 @@ int vfe_enable_output_v2(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); - ops->reg_update_clear(vfe, line->id); + if (ops->reg_update_clear) + ops->reg_update_clear(vfe, line->id); if (output->state > VFE_OUTPUT_RESERVED) { dev_err(vfe->camss->dev, @@ -552,7 +554,9 @@ int vfe_enable_output_v2(struct vfe_line *line) output->gen2.active_num++; ops->vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); - ops->reg_update(vfe, line->id); + + if (!vfe->res->reg_update_after_csid_config) + ops->reg_update(vfe, line->id); } spin_unlock_irqrestore(&vfe->output_lock, flags); @@ -2013,6 +2017,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: ret = 16; break; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index ae9dad353a378..c402ef170c81b 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -133,6 +133,7 @@ struct vfe_isr_ops { struct vfe_subdev_resources { bool is_lite; + bool reg_update_after_csid_config; u8 line_num; bool has_pd; char *pd_name; @@ -249,6 +250,7 @@ extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; extern const struct vfe_hw_ops vfe_ops_gen3; +extern const struct vfe_hw_ops vfe_ops_gen4; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 56dce0dd21688..9409b16a8ea49 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -231,6 +231,142 @@ static const struct camss_subdev_resources csid_res_kaanapali[] = { } }; +/* In Kaanapali, CAMNOC requires all CPAS_TFEX clocks + * to operate on any TFE Full. + */ +static const struct camss_subdev_resources vfe_res_kaanapali[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5731,10 +5867,12 @@ static const struct camss_resources kaanapali_resources = { .pd_name = "top", .csiphy_res = csiphy_res_kaanapali, .csid_res = csid_res_kaanapali, + .vfe_res = vfe_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), .csid_num = ARRAY_SIZE(csid_res_kaanapali), + .vfe_num = ARRAY_SIZE(vfe_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From f872d6522059f15aefe4482ca64fb72674e56ed7 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:31 +0800 Subject: [PATCH 0110/1058] FROMLIST: dt-bindings: media: Add bindings for qcom,x1p42100-camss Add bindings for the Camera Subsystem for X1P42100. The X1P42100 platform provides: - 2 x CSIPHY - 3 x TPG - 3 x CSID - 2 x CSID Lite - 1 x IFE - 2 x IFE Lite Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-1-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,x1p42100-camss.yaml | 424 ++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml new file mode 100644 index 0000000000000..8bfa7e616c3b6 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml @@ -0,0 +1,424 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,x1p42100-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm X1P42100 Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,x1p42100-camss + + reg: + maxItems: 14 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_wrapper + - const: csiphy0 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + + clocks: + maxItems: 22 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe_lite + - const: cphy_rx_clk_src + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 10 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy4 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: top + + vdd-csiphy-0p8-supply: + description: + 0.8V supply to a PHY. + + vdd-csiphy-1p2-supply: + description: + 1.2V supply to a PHY. + + phys: + maxItems: 2 + + phy-names: + items: + - const: csiphy0 + - const: csiphy4 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. + + patternProperties: + "^port@[0-3]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint@0: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving a single sensor input (or first leg of combo). + + properties: + data-lanes: + minItems: 1 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + + required: + - data-lanes + + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb7000 { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "top"; + + vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; + vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From e7f27d2f3758afd6c0b9216d3e0b3f73ac8718d0 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:32 +0800 Subject: [PATCH 0111/1058] FROMLIST: media: qcom: camss: add support for X1P42100 camss The Purwa camera subsystem is a cut-down variant of the Hamoa CAMSS. Compared to Hamoa, Purwa provides only two CSIPHY instances and does not include the VFE1. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-2-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 2 + drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 109 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 4 files changed, 114 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 795b333185e54..4badd4c64e1ef 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1259,6 +1259,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = true; break; } @@ -1358,6 +1359,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); break; case CAMSS_X1E80100: + case CAMSS_X1P42100: regs->lane_regs = &lane_regs_x1e80100[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 826ab85a44a14..dbe5a9af452bf 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -355,6 +355,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2019,6 +2020,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = 16; break; default: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 9409b16a8ea49..6bfaba48b4c9f 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4847,6 +4847,98 @@ static const struct resources_wrapper csid_wrapper_res_x1e80100 = { .reg = "csid_wrapper", }; +static const struct camss_subdev_resources csiphy_res_x1p42100[] = { + /* CSIPHY0 */ + { + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY4 */ + { + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + +static const struct camss_subdev_resources vfe_res_x1p42100[] = { + /* IFE0 */ + { + .regulators = {}, + .clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb", + "vfe0" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 345600000, 432000000, 594000000, 675000000, + 727000000 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .pd_name = "ife0", + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_0 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_1 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -6123,6 +6215,22 @@ static const struct camss_resources x1e80100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; +static const struct camss_resources x1p42100_resources = { + .version = CAMSS_X1P42100, + .pd_name = "top", + .csiphy_res = csiphy_res_x1p42100, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1e80100, + .vfe_res = vfe_res_x1p42100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1e80100, + .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), + .csiphy_num = ARRAY_SIZE(csiphy_res_x1p42100), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), +}; + static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, @@ -6143,6 +6251,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, + { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } }; diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index cea213dc36ebc..6695c26fa8885 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -98,6 +98,7 @@ enum camss_version { CAMSS_8775P, CAMSS_KAANAPALI, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count { From b41ab871f6b022d52b6111c643e9c7885eb311fc Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:03 -0700 Subject: [PATCH 0112/1058] FROMLIST: media: dt-bindings: Add CAMSS device for SM8750 Add bindings for Camera Subsystem (CAMSS) on the Qualcomm SM8750 platform. The SM8750 platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-1-fc6861a65c67@oss.qualcomm.com/ --- .../bindings/media/qcom,sm8750-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml new file mode 100644 index 0000000000000..fc0550899c074 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sm8750-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8750 Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,sm8750-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p9-supply = <&vreg_0p9_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 4433da56740a90dadeba8dce932aa93276ffd9a7 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Tue, 12 May 2026 21:49:27 -0700 Subject: [PATCH 0113/1058] FROMLIST: media: qcom: camss: Add SM8750 compatible camss driver Add SM8750 platform support to the CAMSS driver with ICC bandwidth resources and device tree match entry. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-2-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 6bfaba48b4c9f..ea4627b22b10d 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4534,6 +4534,20 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct resources_icc icc_res_sm8750[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { @@ -6199,6 +6213,13 @@ static const struct camss_resources sm8650_resources = { .vfe_num = ARRAY_SIZE(vfe_res_sm8650), }; +static const struct camss_resources sm8750_resources = { + .version = CAMSS_8750, + .pd_name = "top", + .icc_res = icc_res_sm8750, + .icc_path_num = ARRAY_SIZE(icc_res_sm8750), +}; + static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", @@ -6250,6 +6271,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, + { .compatible = "qcom,sm8750-camss", .data = &sm8750_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 6695c26fa8885..d0f60931cd1fe 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -95,6 +95,7 @@ enum camss_version { CAMSS_845, CAMSS_8550, CAMSS_8650, + CAMSS_8750, CAMSS_8775P, CAMSS_KAANAPALI, CAMSS_X1E80100, From 84e524bf1d2fbf09767442c10f922d6741a53279 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:05 -0700 Subject: [PATCH 0114/1058] FROMLIST: media: qcom: camss: csiphy: Add support for v2.3.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.3.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Additionally, generalize the struct name for the lane configuration that had been added for Kaanapali and use it for SM8750 as well as they share the settings. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-3-fc6861a65c67@oss.qualcomm.com/ --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 5 +- drivers/media/platform/qcom/camss/camss.c | 125 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 4badd4c64e1ef..4c9e2d86e1a90 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -804,7 +804,7 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; -/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +/* 3nm 2PH v 2.3.0/2.4.0 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_2_4_0[] = { /* LN 0 */ @@ -1256,6 +1256,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -1379,7 +1380,9 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_8750: case CAMSS_KAANAPALI: + /* CSPHY v2.4.0 is backward compatible with v2.3.0 settings */ regs->lane_regs = &lane_regs_2_4_0[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index ea4627b22b10d..baa40360885d5 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4534,6 +4534,129 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct camss_subdev_resources csiphy_res_8750[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6216,7 +6339,9 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources sm8750_resources = { .version = CAMSS_8750, .pd_name = "top", + .csiphy_res = csiphy_res_8750, .icc_res = icc_res_sm8750, + .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From 8d642ef1caf26e2daeef64112ba3423cd32acddd Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:06 -0700 Subject: [PATCH 0115/1058] FROMLIST: media: qcom: camss: csid: Add support for CSID 980 Add more detailed resource information for CSID devices along with the driver for CSID 980 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. In SM8750, RUP and AUP updates for the CSID Full modules are split into two registers along with a SET register. However, CSID Lite modules still use a single register to update RUP and AUP without the additional SET register. Handled such differences in the driver. Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-4-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-980.c | 442 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 1 + drivers/media/platform/qcom/camss/camss.c | 75 +++ 4 files changed, 519 insertions(+) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-980.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index b114ca37e36e2..c19d3183882a9 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,6 +8,7 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-980.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ camss-csid-gen4.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-980.c b/drivers/media/platform/qcom/camss/camss-csid-980.c new file mode 100644 index 0000000000000..79eb063000b8d --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-980.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-980.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_LITE_RUP_AUP_CMD 0x18 +#define CSID_LITE_RUP_RDI(rdi) (BIT(4) << (rdi)) +#define CSID_LITE_AUP_RDI(rdi) (BIT(20) << (rdi)) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS (csid_is_lite(csid) ? 0x7C : 0x84) +#define CSID_TOP_IRQ_MASK (csid_is_lite(csid) ? 0x80 : 0x88) +#define CSID_TOP_IRQ_CLEAR (csid_is_lite(csid) ? 0x84 : 0x8C) +#define CSID_TOP_IRQ_SET (csid_is_lite(csid) ? 0x88 : 0x90) +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(csid_is_lite(csid) ? 13 : 3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS (csid_is_lite(csid) ? 0x8C : 0xA4) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 16) +#define CSID_BUF_DONE_IRQ_MASK (csid_is_lite(csid) ? 0x90 : 0xA8) +#define CSID_BUF_DONE_IRQ_CLEAR (csid_is_lite(csid) ? 0x94 : 0xAC) +#define CSID_BUF_DONE_IRQ_SET (csid_is_lite(csid) ? 0x98 : 0xB0) + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS (csid_is_lite(csid) ? 0x9C : 0xB4) +#define CSID_CSI2_RX_IRQ_MASK (csid_is_lite(csid) ? 0xA0 : 0xB8) +#define CSID_CSI2_RX_IRQ_CLEAR (csid_is_lite(csid) ? 0xA4 : 0xBC) +#define CSID_CSI2_RX_IRQ_SET (csid_is_lite(csid) ? 0xA8 : 0xC0) + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 (csid_is_lite(csid) ? 0x200 : 0x400) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 (csid_is_lite(csid) ? 0x204 : 0x404) +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_980 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_CFG0(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x500 + 0x100 * _rdi : \ + 0xE00 + 0x200 * _rdi; \ + }) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_DT_ID 27 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x504 + 0x100 * _rdi : \ + 0xE04 + 0x200 * _rdi; \ + }) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x510 + 0x100 * _rdi : \ + 0xE10 + 0x200 * _rdi; \ + }) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0xE14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) \ + (csid_is_lite(csid) ? 0xEC : 0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) \ + (csid_is_lite(csid) ? 0xF4 : 0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_full_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_AUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_RUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + if (csid_is_lite(csid)) { + csid->reg_update &= ~CSID_LITE_RUP_RDI(port_id); + csid->reg_update &= ~CSID_LITE_AUP_RDI(port_id); + } else { + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); + } +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + val |= dt_id << RDI_CFG0_DT_ID; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + /* Configure pixel store using dedicated register in 980 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) { + __csid_aup_update(csid, i); + __csid_rup_update(csid, i); + } + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_980 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; + diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index e6590b2bd8be5..dd9c0868e9c73 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -224,6 +224,7 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_980; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; extern const struct csid_hw_ops csid_ops_gen4; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index baa40360885d5..ffbad28801b5a 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4657,6 +4657,79 @@ static const struct camss_subdev_resources csiphy_res_8750[] = { }, }; +static const struct camss_subdev_resources csid_res_8750[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6340,8 +6413,10 @@ static const struct camss_resources sm8750_resources = { .version = CAMSS_8750, .pd_name = "top", .csiphy_res = csiphy_res_8750, + .csid_res = csid_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), + .csid_num = ARRAY_SIZE(csid_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From e0c979ae8090228804d0e3adcda7605fcff1ebdb Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:07 -0700 Subject: [PATCH 0116/1058] FROMLIST: media: qcom: camss: vfe: Add support for VFE 980 Add support for Video Front End (VFE) that is on the SM8750 SoCs. VFE gen4 has support for VFE 980. This change limits SM8750 VFE output lines to 3 for now as constrained by the CAMSS driver framework. Reviewed-by: Bryan O'Donoghue Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-5-fc6861a65c67@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-vfe-gen4.c | 10 +- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 135 ++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index d73d70898710a..46d8e61b9bac0 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -13,8 +13,12 @@ #include "camss.h" #include "camss-vfe.h" -/* VFE-gen4 Bus Register Base Addresses */ -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define IS_VFE_980(vfe) ((vfe)->camss->res->version == CAMSS_8750) + +#define BUS_REG_BASE_980 (vfe_is_lite(vfe) ? 0x200 : 0x800) +#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define BUS_REG_BASE \ + (IS_VFE_980(vfe) ? BUS_REG_BASE_980 : BUS_REG_BASE_1080) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) @@ -55,7 +59,7 @@ * DISPLAY_DS2_C 6 * FD_Y 7 * FD_C 8 - * PIXEL_RAW 9 + * RAW_OUT(1080)/IR_OUT(980) 9 * STATS_AEC_BG 10 * STATS_AEC_BHIST 11 * STATS_TINTLESS_BG 12 diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index dbe5a9af452bf..57c5be461c3b4 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -352,6 +352,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -2017,6 +2018,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index ffbad28801b5a..da687d54be9c6 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4730,6 +4730,139 @@ static const struct camss_subdev_resources csid_res_8750[] = { } }; +static const struct camss_subdev_resources vfe_res_8750[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE0 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE1 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6414,9 +6547,11 @@ static const struct camss_resources sm8750_resources = { .pd_name = "top", .csiphy_res = csiphy_res_8750, .csid_res = csid_res_8750, + .vfe_res = vfe_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .csid_num = ARRAY_SIZE(csid_res_8750), + .vfe_num = ARRAY_SIZE(vfe_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From 22cf55dbb7b700514c69246685944c1bbfaa0e19 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 19 May 2026 14:29:37 +0530 Subject: [PATCH 0117/1058] FROMLIST: dt-bindings: media: Add bindings for qcom,glymur-camss Add device tree bindings for the Camera Subsystem (CAMSS) on the Qualcomm Glymur platform. The Glymur platform provides: - 3 x CSIPHY (CSI Physical Layer) - 3 x CSID (CSI Decoder), 2 x CSID Lite - 3 x TPG (Test Pattern Generator) - 2 x VFE (Video Front End), 2 x VFE Lite Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-1-bee535396d22@oss.qualcomm.com/ --- .../bindings/media/qcom,glymur-camss.yaml | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml new file mode 100644 index 0000000000000..5596f3fb99003 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml @@ -0,0 +1,343 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur Camera Subsystem (CAMSS) + +maintainers: + - Nihal Kumar Gupta + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,glymur-camss + + reg: + maxItems: 16 + + reg-names: + items: + - const: csid_wrapper + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 26 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 12 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: top + + vdd-csiphy-0p8-supply: + description: + Phandle to 0.8V regulator supply to CSI PHYs. + + vdd-csiphy-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSI PHYs pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-2]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb6000 { + compatible = "qcom,glymur-camss"; + + reg = <0x0 0x0acb6000 0x0 0x1000>, + <0x0 0x0acb7000 0x0 0x2000>, + <0x0 0x0acb9000 0x0 0x2000>, + <0x0 0x0acbb000 0x0 0x2000>, + <0x0 0x0acc6000 0x0 0x1000>, + <0x0 0x0acca000 0x0 0x1000>, + <0x0 0x0ace4000 0x0 0x2000>, + <0x0 0x0ace6000 0x0 0x2000>, + <0x0 0x0acec000 0x0 0x2000>, + <0x0 0x0acf6000 0x0 0x1000>, + <0x0 0x0acf7000 0x0 0x1000>, + <0x0 0x0acf8000 0x0 0x1000>, + <0x0 0x0ac62000 0x0 0xf000>, + <0x0 0x0ac71000 0x0 0xf000>, + <0x0 0x0acc7000 0x0 0x2000>, + <0x0 0x0accb000 0x0 0x2000>; + + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x00>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "ife1", + "top"; + + vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; + vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + csiphy_ep0: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From ac7a3ed92ef6d89ede2957b3f6f6ba19b4ea9844 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 10:44:33 +0530 Subject: [PATCH 0118/1058] FROMLIST: media: qcom: camss: Add Glymur compatible Add CAMSS_GLYMUR enum, Glymur compatible and Glymur camss driver private data, the private data just include some basic information for now, later changes will enumerate with csiphy, tpg, csid and vfe resources. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-3-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 7 +++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index da687d54be9c6..c5f9688ee2966 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6587,7 +6587,14 @@ static const struct camss_resources x1p42100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), }; +static const struct camss_resources glymur_resources = { + .version = CAMSS_GLYMUR, + .pd_name = "top", + .legacy_phy = true, +}; + static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,glymur-camss", .data = &glymur_resources }, { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index d0f60931cd1fe..7cd35c838d74a 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -97,6 +97,7 @@ enum camss_version { CAMSS_8650, CAMSS_8750, CAMSS_8775P, + CAMSS_GLYMUR, CAMSS_KAANAPALI, CAMSS_X1E80100, CAMSS_X1P42100, From c2afdd9e02691f82b901f0c58f20749ccdca0b01 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 10:57:02 +0530 Subject: [PATCH 0119/1058] FROMLIST: media: qcom: camss: Add CSIPHY support for Glymur Glymur uses the same CSIPHY hardware version as x1e80100. The only difference between the two platforms is the number of CSIPHY instances. x1e80100 has four, while Glymur has three. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-4-bee535396d22@oss.qualcomm.com/ --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 2 + drivers/media/platform/qcom/camss/camss.c | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 4c9e2d86e1a90..6de38deb63b97 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1258,6 +1258,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: @@ -1359,6 +1360,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sc8280xp[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); break; + case CAMSS_GLYMUR: case CAMSS_X1E80100: case CAMSS_X1P42100: regs->lane_regs = &lane_regs_x1e80100[0]; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c5f9688ee2966..e4b5b5634ffeb 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5282,6 +5282,60 @@ static const struct camss_subdev_resources vfe_res_x1p42100[] = { }, }; +static const struct camss_subdev_resources csiphy_res_glymur[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate From c62106d768f82a42aae0071cbada6252c5055a78 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 11:03:09 +0530 Subject: [PATCH 0120/1058] FROMLIST: media: qcom: camss: enable vfe for Glymur Extend vfe_src_pad_code() and vfe_bpl_align() for Glymur. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-5-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss-vfe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 57c5be461c3b4..36e39d55a4a8c 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -354,6 +354,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: @@ -2020,6 +2021,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: From 1d585a2988b77af4a4cb3a23321d82cf8ede3df0 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 11:07:06 +0530 Subject: [PATCH 0121/1058] FROMLIST: media: qcom: camss: Enumerate resources for Glymur Enumerate csiphy, csid and vfe resources for Glymur. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-6-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e4b5b5634ffeb..c98430a05a960 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6645,6 +6645,17 @@ static const struct camss_resources glymur_resources = { .version = CAMSS_GLYMUR, .pd_name = "top", .legacy_phy = true, + .csiphy_res = csiphy_res_glymur, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1e80100, + .vfe_res = vfe_res_x1e80100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1e80100, + .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), + .csiphy_num = ARRAY_SIZE(csiphy_res_glymur), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; static const struct of_device_id camss_dt_match[] = { From 321ea9fd6c14a3636cc0e8bed24d1bee0ed09c29 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Fri, 15 May 2026 19:16:22 +0530 Subject: [PATCH 0122/1058] FROMLIST: media: qcom: camss: add support for QCM2390 camss Add CAMSS driver support for Shikra SoC. Add high level resource definitions for 2 CSIPHY, 2 CSID and 2 VFE instances along with the interconnect bandwidth votes for AHB, HF and SF MNOC paths. Signed-off-by: Prashant Shrotriya Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260526-shikra-camss-review-v1-3-645d2c8c75a7@qti.qualcomm.com/ --- .../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 2 ++ drivers/media/platform/qcom/camss/camss-vfe.c | 1 + drivers/media/platform/qcom/camss/camss.c | 14 ++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 4 files changed, 18 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 6de38deb63b97..75c0aef3725e2 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1247,6 +1247,7 @@ static bool csiphy_is_gen2(u32 version) switch (version) { case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -1343,6 +1344,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: regs->lane_regs = &lane_regs_qcm2290[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 36e39d55a4a8c..c12814085b077 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -342,6 +342,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, break; case CAMSS_660: case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c98430a05a960..a00af0c718dcd 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6427,6 +6427,19 @@ static const struct camss_resources qcm2290_resources = { .vfe_num = ARRAY_SIZE(vfe_res_2290), }; +static const struct camss_resources qcm2390_resources = { + .version = CAMSS_2390, + .legacy_phy = true, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", @@ -6673,6 +6686,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm670-camss", .data = &sdm670_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, + { .compatible = "qcom,shikra-camss", .data = &qcm2390_resources }, { .compatible = "qcom,sm6150-camss", .data = &sm6150_resources }, { .compatible = "qcom,sm6350-camss", .data = &sm6350_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 7cd35c838d74a..91438769419e5 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -82,6 +82,7 @@ enum pm_domain { enum camss_version { CAMSS_660, CAMSS_2290, + CAMSS_2390, CAMSS_6150, CAMSS_6350, CAMSS_7280, From c394dfb4b3768df4d41b9b32bf310c307451fa68 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 25 Jun 2026 17:42:45 +0800 Subject: [PATCH 0123/1058] FROMLIST: i2c: qcom-cci: drop custom suspend/resume and rely on runtime PM helpers cci_resume() unconditionally calls cci_resume_runtime() regardless of the runtime PM state. If the device is already runtime-suspended before system suspend, the clock is re-enabled while runtime_status remains RPM_SUSPENDED. As a result, pm_request_autosuspend() does not arm the timer, leaving the clock permanently enabled. Fixes: e517526195de ("i2c: Add Qualcomm CCI I2C driver") Cc: stable@vger.kernel.org Reviewed-by: Vladimir Zapolskiy Reviewed-by: Konrad Dybcio Reviewed-by: Loic Poulain Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260625-cci-v1-1-a100cda673ce@oss.qualcomm.com/ --- drivers/i2c/busses/i2c-qcom-cci.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 4d64895a9e9e4..bdeda3979c481 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -492,24 +492,8 @@ static int __maybe_unused cci_resume_runtime(struct device *dev) return 0; } -static int __maybe_unused cci_suspend(struct device *dev) -{ - if (!pm_runtime_suspended(dev)) - return cci_suspend_runtime(dev); - - return 0; -} - -static int __maybe_unused cci_resume(struct device *dev) -{ - cci_resume_runtime(dev); - pm_request_autosuspend(dev); - - return 0; -} - static const struct dev_pm_ops qcom_cci_pm = { - SET_SYSTEM_SLEEP_PM_OPS(cci_suspend, cci_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL) }; From 9b660d0b6b7cdea95aa44a25e44dbf6d273a9617 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:50 -0800 Subject: [PATCH 0124/1058] FROMLIST: coresight-tmc: Defer probe when associated CPUs are offline On some platforms, the TMC driver may probe before the associated CPUs are online. This prevents the driver from securely accessing the hardware or configuring it via smp_call_function_single(), which requires the target CPU to be available. To address this, defer the hardware initialization if the associated CPUs are offline: 1. Track such deferred devices in a global list. 2. Register a CPU hotplug callback (`tmc_online_cpu`) to detect when a relevant CPU comes online. 3. Upon CPU online, retry the hardware initialization and registration for the waiting TMC devices. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-10-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- .../hwtracing/coresight/coresight-tmc-core.c | 60 ++++++++++++++++++- drivers/hwtracing/coresight/coresight-tmc.h | 4 ++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 4224ee21570c5..190cade689094 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -33,6 +33,10 @@ #include "coresight-priv.h" #include "coresight-tmc.h" +static LIST_HEAD(tmc_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + int tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; @@ -1017,6 +1021,8 @@ static int __tmc_probe(struct device *dev, struct resource *res) if (!drvdata->supported_cpus) return -EINVAL; + drvdata->dev = dev; + cpus_read_lock(); for_each_cpu(cpu, drvdata->supported_cpus) { ret = smp_call_function_single(cpu, @@ -1024,11 +1030,16 @@ static int __tmc_probe(struct device *dev, struct resource *res) if (!ret) break; } - cpus_read_unlock(); + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &tmc_delay_probe); + cpus_read_unlock(); ret = 0; goto out; } + + cpus_read_unlock(); } else { tmc_init_hw_config(drvdata); } @@ -1093,8 +1104,12 @@ static void __tmc_remove(struct device *dev) misc_deregister(&drvdata->miscdev); if (drvdata->crashdev.fops) misc_deregister(&drvdata->crashdev); - if (drvdata->csdev) + if (drvdata->csdev) { coresight_unregister(drvdata->csdev); + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } } static void tmc_remove(struct amba_device *adev) @@ -1205,14 +1220,55 @@ static struct platform_driver tmc_platform_driver = { }, }; +static int tmc_online_cpu(unsigned int cpu) +{ + struct tmc_drvdata *drvdata, *tmp; + int ret; + + spin_lock(&delay_lock); + list_for_each_entry_safe(drvdata, tmp, &tmc_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + list_del(&drvdata->link); + + spin_unlock(&delay_lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + tmc_init_hw_config(drvdata); + tmc_clear_self_claim_tag(drvdata); + tmc_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + spin_lock(&delay_lock); + } + } + spin_unlock(&delay_lock); + return 0; +} + static int __init tmc_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-tmc:online", + tmc_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver); } static void __exit tmc_exit(void) { coresight_remove_driver(&tmc_driver, &tmc_platform_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(tmc_init); module_exit(tmc_exit); diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index fc514cd69df2a..1898da4ad6988 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -266,6 +266,8 @@ struct etr_buf_node { * @supported_cpus: Represent the CPUs related to this TMC. * @devid: TMC variant ID inferred from the device configuration register. * @desc_name: Name to be used while creating crash interface. + * @dev: pointer to the device associated with this TMC. + * @link: link to the delay_probed list. */ struct tmc_drvdata { struct clk *atclk; @@ -301,6 +303,8 @@ struct tmc_drvdata { struct cpumask *supported_cpus; u32 devid; const char *desc_name; + struct device *dev; + struct list_head link; }; /** From b49acdc05145ab59a66863896a29ae9fc2fde040 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Thu, 18 Dec 2025 00:09:51 -0800 Subject: [PATCH 0125/1058] FROMLIST: coresight: Pass trace mode to link enable callback Currently, the link enable callback does not receive the CoreSight mode (enum cs_mode). This prevents link drivers from knowing whether they are being enabled for SysFS or Perf. This distinction is crucial because Perf mode runs in atomic context, where certain operations (like smp_call_function_single()) are unsafe. Without knowing the mode, drivers cannot conditionally avoid these unsafe calls. Update the `enable` callback in `struct coresight_ops_link` to accept `enum cs_mode`. This allows drivers to implement mode-specific logic, such as using atomic-safe enablement sequences when running in Perf mode. Update all call sites and driver implementations accordingly. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-11-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-core.c | 7 +++--- .../hwtracing/coresight/coresight-funnel.c | 21 ++++++++++++++++- .../coresight/coresight-replicator.c | 23 ++++++++++++++++++- .../hwtracing/coresight/coresight-tmc-etf.c | 19 ++++++++++++++- drivers/hwtracing/coresight/coresight-tnoc.c | 3 ++- drivers/hwtracing/coresight/coresight-tpda.c | 3 ++- include/linux/coresight.h | 3 ++- 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 7a7a85acdca0d..0dc80a2acdfac 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -415,7 +415,8 @@ static void coresight_disable_sink(struct coresight_device *csdev) static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child, - struct coresight_device *source) + struct coresight_device *source, + enum cs_mode mode) { int link_subtype; struct coresight_connection *inconn, *outconn; @@ -432,7 +433,7 @@ static int coresight_enable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn)) return PTR_ERR(outconn); - return link_ops(csdev)->enable(csdev, inconn, outconn); + return link_ops(csdev)->enable(csdev, inconn, outconn, mode); } static void coresight_disable_link(struct coresight_device *csdev, @@ -716,7 +717,7 @@ static int coresight_enable_path_from_to(struct coresight_path *path, parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child, - coresight_get_source(path)); + coresight_get_source(path), mode); if (ret) goto err_disable_helpers; break; diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 8cfebe4cbd216..b175f8db4210f 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -120,7 +120,8 @@ static int funnel_enable_hw(struct funnel_drvdata *drvdata, int port) static int funnel_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int rc = 0; struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -134,6 +135,23 @@ static int funnel_enable(struct coresight_device *csdev, else in->dest_refcnt++; + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + if (drvdata->base) + rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); + if (!rc) + in->dest_refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return rc; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) { @@ -182,6 +200,7 @@ static void funnel_disable(struct coresight_device *csdev, dynamic_funnel_disable_hw(drvdata, in->dest_port); last_disable = true; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index d4f31f03cf23c..9f488ed103087 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -198,7 +198,8 @@ static int replicator_enable_hw(struct replicator_drvdata *drvdata, static int replicator_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int rc = 0; struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -211,6 +212,25 @@ static int replicator_enable(struct coresight_device *csdev, first_enable = true; else out->src_refcnt++; + + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + if (drvdata->base) + rc = dynamic_replicator_enable(drvdata, in->dest_port, + out->src_port); + if (!rc) + out->src_refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return rc; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) { @@ -271,6 +291,7 @@ static void replicator_disable(struct coresight_device *csdev, out->src_port); last_disable = true; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 11357788e9d93..f1b8264b4e5c8 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -427,7 +427,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) static int tmc_enable_etf_link(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int ret = 0; unsigned long flags; @@ -446,6 +447,22 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, if (!first_enable) csdev->refcnt++; + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + ret = tmc_etf_enable_hw_local(drvdata); + if (!ret) + csdev->refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) { ret = tmc_etf_enable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 9e8de4323d285..5fb27291984fa 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -79,7 +79,8 @@ static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata) } static int trace_noc_enable(struct coresight_device *csdev, struct coresight_connection *inport, - struct coresight_connection *outport) + struct coresight_connection *outport, + enum cs_mode mode) { struct trace_noc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 89c8f71f0aff0..e0084eed4843f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -222,7 +222,8 @@ static int __tpda_enable(struct tpda_drvdata *drvdata, int port) static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret = 0; diff --git a/include/linux/coresight.h b/include/linux/coresight.h index ddf18c970e343..7beb70f9990a3 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -388,7 +388,8 @@ struct coresight_ops_sink { struct coresight_ops_link { int (*enable)(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out); + struct coresight_connection *out, + enum cs_mode mode); void (*disable)(struct coresight_device *csdev, struct coresight_connection *in, struct coresight_connection *out); From ee4a490ad48a7236b3f417efda48cc1393d2e0d9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 3 Feb 2026 14:39:38 +0800 Subject: [PATCH 0126/1058] FROMLIST: dt-binding: document QCOM platforms for CTCU device Document the platforms that fallback to using the qcom,sa8775p-ctcu compatible for probing. Link: https://lore.kernel.org/all/20260204-enable-ctcu-and-etr-v3-1-0bb95c590ae1@oss.qualcomm.com/ Signed-off-by: Jie Gan --- .../devicetree/bindings/arm/qcom,coresight-ctcu.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml index 2981001a7d7f7..468da6439bbf9 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml @@ -29,7 +29,11 @@ properties: oneOf: - items: - enum: + - qcom,glymur-ctcu + - qcom,kaanapali-ctcu - qcom,qcs8300-ctcu + - qcom,sm8750-ctcu + - qcom,x1e80100-ctcu - const: qcom,sa8775p-ctcu - enum: - qcom,sa8775p-ctcu From e6e5a531c5dea99979b5fad6cec012279075d3ad Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Tue, 24 Mar 2026 15:25:55 +0800 Subject: [PATCH 0127/1058] FROMLIST: misc: fastrpc: fix UAF and kernel panic during cleanup on process abort When a userspace FastRPC client is abruptly terminated, FastRPC cleanup paths can race with device and session teardown. This results in kernel panics in different release paths: - fastrpc_release() when using remote heap, originating from fastrpc_buf_free() - fastrpc_device_release() when using system heap, originating from fastrpc_free_map() In addition, fastrpc_map_put() may trigger refcount use-after-free due to concurrent cleanup without proper synchronization. The root cause is that buffer and map cleanup paths may access map and buf resources after the associated device or session has already been released. Fix this by: - Introducing mutex protection for map and buf lifetime - Serializing buffer and map cleanup against device teardown - Skipping buffer and map operations when the device is already gone These changes ensure cleanup paths are safe against unexpected process aborts and prevent use-after-free and kernel panic scenarios. Link: https://lore.kernel.org/all/20260427105310.4056-1-jianping.li@oss.qualcomm.com/ Fixes: c68cfb718c8f9 ("misc: fastrpc: Add support for context Invoke method") Cc: stable@kernel.org Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 58 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index f3a49384586d1..eed9fe69c6add 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -255,6 +255,8 @@ struct fastrpc_session_ctx { int sid; bool used; bool valid; + bool allocated; + struct mutex mutex; }; struct fastrpc_soc_data { @@ -335,9 +337,14 @@ static inline u64 fastrpc_sid_offset(struct fastrpc_channel_ctx *cctx, static void fastrpc_free_map(struct kref *ref) { struct fastrpc_map *map; + struct fastrpc_user *fl; map = container_of(ref, struct fastrpc_map, refcount); + fl = map->fl; + if (!fl) + return; + if (map->table) { if (map->attr & FASTRPC_ATTR_SECUREMAP) { struct qcom_scm_vmperm perm; @@ -356,10 +363,16 @@ static void fastrpc_free_map(struct kref *ref) return; } } + mutex_lock(&fl->sctx->mutex); + if (!fl->sctx->dev) { + mutex_unlock(&fl->sctx->mutex); + return; + } dma_buf_unmap_attachment_unlocked(map->attach, map->table, DMA_BIDIRECTIONAL); dma_buf_detach(map->buf, map->attach); dma_buf_put(map->buf); + mutex_unlock(&fl->sctx->mutex); } if (map->fl) { @@ -422,9 +435,18 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { - dma_free_coherent(buf->dev, buf->size, buf->virt, - fastrpc_ipa_to_dma_addr(buf->fl->cctx, buf->dma_addr)); - kfree(buf); + struct fastrpc_user *fl = buf->fl; + + if (!fl) + return; + mutex_lock(&fl->sctx->mutex); + if (fl->sctx->dev) { + dma_free_coherent(buf->dev, buf->size, buf->virt, + fastrpc_ipa_to_dma_addr(buf->fl->cctx, + buf->dma_addr)); + kfree(buf); + } + mutex_unlock(&fl->sctx->mutex); } static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, @@ -447,8 +469,11 @@ static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, buf->dev = dev; buf->raddr = 0; - buf->virt = dma_alloc_coherent(dev, buf->size, &buf->dma_addr, - GFP_KERNEL); + mutex_lock(&fl->sctx->mutex); + if (fl->sctx->dev) + buf->virt = dma_alloc_coherent(dev, buf->size, &buf->dma_addr, + GFP_KERNEL); + mutex_unlock(&fl->sctx->mutex); if (!buf->virt) { mutex_destroy(&buf->lock); kfree(buf); @@ -491,6 +516,10 @@ static void fastrpc_channel_ctx_free(struct kref *ref) struct fastrpc_channel_ctx *cctx; cctx = container_of(ref, struct fastrpc_channel_ctx, refcount); + for (int i = 0; i < FASTRPC_MAX_SESSIONS; i++) { + if (cctx->session[i].allocated) + mutex_destroy(&cctx->session[i].mutex); + } kfree(cctx); } @@ -855,19 +884,29 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, goto get_err; } + mutex_lock(&fl->sctx->mutex); + if (!fl->sctx->dev) { + err = -ENODEV; + mutex_unlock(&fl->sctx->mutex); + goto attach_err; + } + map->attach = dma_buf_attach(map->buf, sess->dev); if (IS_ERR(map->attach)) { dev_err(sess->dev, "Failed to attach dmabuf\n"); err = PTR_ERR(map->attach); + mutex_unlock(&fl->sctx->mutex); goto attach_err; } table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL); if (IS_ERR(table)) { err = PTR_ERR(table); + mutex_unlock(&fl->sctx->mutex); goto map_err; } map->table = table; + mutex_unlock(&fl->sctx->mutex); if (attr & FASTRPC_ATTR_SECUREMAP) map->dma_addr = sg_phys(map->table->sgl); @@ -2243,6 +2282,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + mutex_init(&sess->mutex); + sess->allocated = true; dev_set_drvdata(dev, sess); if (cctx->domain_id == CDSP_DOMAIN_ID) @@ -2259,6 +2300,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev) break; dup_sess = &cctx->session[cctx->sesscount++]; memcpy(dup_sess, sess, sizeof(*dup_sess)); + mutex_init(&dup_sess->mutex); + dup_sess->allocated = true; } } spin_unlock_irqrestore(&cctx->lock, flags); @@ -2281,6 +2324,11 @@ static void fastrpc_cb_remove(struct platform_device *pdev) spin_lock_irqsave(&cctx->lock, flags); for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { if (cctx->session[i].sid == sess->sid) { + spin_unlock_irqrestore(&cctx->lock, flags); + mutex_lock(&cctx->session[i].mutex); + cctx->session[i].dev = NULL; + mutex_unlock(&cctx->session[i].mutex); + spin_lock_irqsave(&cctx->lock, flags); cctx->session[i].valid = false; cctx->sesscount--; } From 58bf7207a1453d3505ad43536575108e8f6ff0df Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Tue, 19 May 2026 17:40:19 +0800 Subject: [PATCH 0128/1058] FROMLIST: fastrpc: Reduce log level for DSP info and reserved memory messages On some platforms (e.g. QCS615 Talos), fastrpc may temporarily fail to retrieve DSP attributes during boot, resulting in repeated "Error: dsp information is incorrect" messages printed on the console. These messages are observed continuously during boot when metadata flashing is enabled as part of RC releases, causing unnecessary log noise. Similarly, the absence of reserved DMA memory is a valid configuration and does not represent an error condition. Since these scenarios are expected and do not indicate a failure, downgrade the log level from dev_err/dev_info to dev_dbg to avoid flooding the console. No functional change intended. Link: https://lore.kernel.org/all/20260514062825.50172-1-jianping.li@oss.qualcomm.com/ Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index eed9fe69c6add..cc19050274a0c 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1867,7 +1867,7 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap, kfree(dsp_attributes); return -EOPNOTSUPP; } else if (err) { - dev_err(&cctx->rpdev->dev, "Error: dsp information is incorrect err: %d\n", err); + dev_dbg(&cctx->rpdev->dev, "Error: dsp information is incorrect err: %d\n", err); kfree(dsp_attributes); return err; } @@ -2435,7 +2435,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } if (of_reserved_mem_device_init_by_idx(rdev, rdev->of_node, 0)) - dev_info(rdev, "no reserved DMA memory for FASTRPC\n"); + dev_dbg(rdev, "no reserved DMA memory for FASTRPC\n"); vmcount = of_property_read_variable_u32_array(rdev->of_node, "qcom,vmids", &vmids[0], 0, FASTRPC_MAX_VMIDS); From 5114836b48ca9e8a4327f0ed71eb9fffc54954a3 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:23 +0530 Subject: [PATCH 0129/1058] FROMLIST: misc: fastrpc: Fix initial memory allocation for Audio PD memory pool The initial buffer allocated for the Audio PD memory pool is never added to the pool because pageslen is set to 0. As a result, the buffer is not registered with Audio PD and is never used, causing a memory leak. Audio PD immediately falls back to allocating memory from the remote heap since the pool starts out empty. Fix this by setting pageslen to 1 so that the initially allocated buffer is correctly registered and becomes part of the Audio PD memory pool. Link: https://lore.kernel.org/all/20260609025938.457-2-jianping.li@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index cc19050274a0c..340443e5929fa 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1409,7 +1409,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, err = PTR_ERR(name); goto err; } - + inbuf.client_id = fl->client_id; + inbuf.namelen = init.namelen; + inbuf.pageslen = 0; if (!fl->cctx->remote_heap) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &fl->cctx->remote_heap); @@ -1432,12 +1434,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err_map; } scm_done = true; + inbuf.pageslen = 1; } } - inbuf.client_id = fl->client_id; - inbuf.namelen = init.namelen; - inbuf.pageslen = 0; fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; From 70ac9be5e8d1861a479df77add55ba70fcc1ebcb Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:24 +0530 Subject: [PATCH 0130/1058] FROMLIST: misc: fastrpc: Remove buffer from list prior to unmap operation fastrpc_req_munmap_impl() is called to unmap any buffer. The buffer is getting removed from the list after it is unmapped from DSP. This can create potential race conditions if multiple threads invoke unmap concurrently, where one thread may remove the entry from the list while another thread's unmap operation is still ongoing. Fix this by removing the buffer entry from the list before calling the unmap operation. If the unmap fails, the entry is re-added to the list so that userspace can retry the unmap, or alternatively, the buffer will be cleaned up during device release when the DSP process is torn down and all DSP-side mappings are freed along with remaining buffers in the list. Link: https://lore.kernel.org/all/20260609025938.457-3-jianping.li@oss.qualcomm.com/ Fixes: 2419e55e532de ("misc: fastrpc: add mmap/unmap support") Cc: stable@kernel.org Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 340443e5929fa..4a8c4cf95641c 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1928,9 +1928,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1944,6 +1941,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_buf *buf = NULL, *iter, *b; struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; + int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1951,6 +1949,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { + list_del(&iter->node); buf = iter; break; } @@ -1963,7 +1962,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - return fastrpc_req_munmap_impl(fl, buf); + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); + } + + return err; } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) From 7beadd6d63a2b7e3fdeae0089bea34384d5e3a62 Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Tue, 23 Dec 2025 15:50:59 +0800 Subject: [PATCH 0131/1058] FROMLIST: misc: fastrpc: Allocate entire reserved memory for Audio PD in probe Allocating and freeing Audio PD memory from userspace is unsafe because the kernel cannot reliably determine when the DSP has finished using the memory. Userspace may free buffers while they are still in use by the DSP, and remote free requests cannot be safely trusted. Additionally, the current implementation allows userspace to repeatedly grow the Audio PD heap, but does not support shrinking it. This can lead to unbounded memory usage over time, effectively causing a memory leak. Fix this by allocating the entire Audio PD reserved-memory region during rpmsg probe and tying its lifetime to the rpmsg channel. This removes userspace-controlled alloc/free and ensures that memory is reclaimed only when the DSP process is torn down. Add explicit validation for remote_heap presence and size before sending the memory to DSP, and fail early if the reserved-memory region is missing or incomplete. Link: https://lore.kernel.org/all/20260609025938.457-4-jianping.li@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 112 ++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 4a8c4cf95641c..a92d81fd52f76 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -278,6 +278,8 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; + /* Flag if audio PD init mem was allocated */ + bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -1380,15 +1382,24 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; + struct fastrpc_channel_ctx *cctx = fl->cctx; char *name; int err; - bool scm_done = false; struct { int client_id; u32 namelen; u32 pageslen; } inbuf; u32 sc; + unsigned long flags; + + if (!cctx->remote_heap || !cctx->remote_heap->dma_addr || + !cctx->remote_heap->size) { + err = -ENOMEM; + dev_err(fl->sctx->dev, + "remote heap memory region is not added\n"); + return err; + } args = kzalloc_objs(*args, FASTRPC_CREATE_STATIC_PROCESS_NARGS); if (!args) @@ -1412,31 +1423,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, inbuf.client_id = fl->client_id; inbuf.namelen = init.namelen; inbuf.pageslen = 0; - if (!fl->cctx->remote_heap) { - err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, - &fl->cctx->remote_heap); - if (err) - goto err_name; - - /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ - if (fl->cctx->vmcount) { - u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); - - err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr, - (u64)fl->cctx->remote_heap->size, - &src_perms, - fl->cctx->vmperms, fl->cctx->vmcount); - if (err) { - dev_err(fl->sctx->dev, - "Failed to assign memory with dma_addr %pad size 0x%llx err %d\n", - &fl->cctx->remote_heap->dma_addr, - fl->cctx->remote_heap->size, err); - goto err_map; - } - scm_done = true; - inbuf.pageslen = 1; - } - } fl->pd = USER_PD; @@ -1448,8 +1434,17 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - pages[0].addr = fl->cctx->remote_heap->dma_addr; - pages[0].size = fl->cctx->remote_heap->size; + spin_lock_irqsave(&cctx->lock, flags); + if (!cctx->audio_init_mem) { + pages[0].addr = cctx->remote_heap->dma_addr; + pages[0].size = cctx->remote_heap->size; + cctx->audio_init_mem = true; + inbuf.pageslen = 1; + } else { + pages[0].addr = 0; + pages[0].size = 0; + } + spin_unlock_irqrestore(&cctx->lock, flags); args[2].ptr = (u64)(uintptr_t) pages; args[2].length = sizeof(*pages); @@ -1467,27 +1462,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: - if (fl->cctx->vmcount && scm_done) { - u64 src_perms = 0; - struct qcom_scm_vmperm dst_perms; - u32 i; - - for (i = 0; i < fl->cctx->vmcount; i++) - src_perms |= BIT(fl->cctx->vmperms[i].vmid); - - dst_perms.vmid = QCOM_SCM_VMID_HLOS; - dst_perms.perm = QCOM_SCM_PERM_RWX; - err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr, - (u64)fl->cctx->remote_heap->size, - &src_perms, &dst_perms, 1); - if (err) - dev_err(fl->sctx->dev, "Failed to assign memory dma_addr %pad size 0x%llx err %d\n", - &fl->cctx->remote_heap->dma_addr, fl->cctx->remote_heap->size, err); - } -err_map: - fastrpc_buf_free(fl->cctx->remote_heap); - fl->cctx->remote_heap = NULL; -err_name: + cctx->audio_init_mem = false; kfree(name); err: kfree(args); @@ -2462,12 +2437,23 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } - if (domain_id == SDSP_DOMAIN_ID) { + if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) { struct resource res; u64 src_perms; err = of_reserved_mem_region_to_resource(rdev->of_node, 0, &res); if (!err) { + if (domain_id == ADSP_DOMAIN_ID) { + data->remote_heap = + kzalloc_obj(*data->remote_heap, GFP_KERNEL); + if (!data->remote_heap) { + err = -ENOMEM; + goto err_free_data; + } + + data->remote_heap->dma_addr = res.start; + data->remote_heap->size = resource_size(&res); + } src_perms = BIT(QCOM_SCM_VMID_HLOS); err = qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, @@ -2475,7 +2461,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_free_data; } - } secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); @@ -2534,6 +2519,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) misc_deregister(&data->secure_fdevice->miscdev); err_free_data: + kfree(data->remote_heap); kfree(data); return err; } @@ -2556,6 +2542,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_buf *buf, *b; struct fastrpc_user *user; unsigned long flags; + int err; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2573,8 +2560,27 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap) - fastrpc_buf_free(cctx->remote_heap); + if (cctx->remote_heap && cctx->vmcount) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + + for (u32 i = 0; i < cctx->vmcount; i++) + src_perms |= BIT(cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + + err = qcom_scm_assign_mem(cctx->remote_heap->dma_addr, + cctx->remote_heap->size, &src_perms, + &dst_perms, 1); + if (err) + dev_err(&rpdev->dev, + "Failed to assign memory back to HLOS: dma_addr %pad size %#llx err %d\n", + &cctx->remote_heap->dma_addr, cctx->remote_heap->size, err); + } + + kfree(cctx->remote_heap); + cctx->remote_heap = NULL; of_platform_depopulate(&rpdev->dev); From ca3387e5cd5ca129a558d3240dbd1084a81c4395 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 13 May 2025 09:58:21 +0530 Subject: [PATCH 0132/1058] FROMLIST: misc: fastrpc: Allow fastrpc_buf_free() to accept NULL Make fastrpc_buf_free() a no-op when passed a NULL pointer, allowing callers to avoid open-coded NULL checks. Link: https://lore.kernel.org/all/20260609025938.457-5-jianping.li@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index a92d81fd52f76..38ea79a47c4cf 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -437,6 +437,9 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { + if (!buf) + return; + struct fastrpc_user *fl = buf->fl; if (!fl) @@ -545,8 +548,7 @@ static void fastrpc_user_free(struct kref *ref) struct fastrpc_map *map, *m; struct fastrpc_buf *buf, *b; - if (fl->init_mem) - fastrpc_buf_free(fl->init_mem); + fastrpc_buf_free(fl->init_mem); list_for_each_entry_safe(ctx, n, &fl->pending, node) { list_del(&ctx->node); @@ -591,8 +593,7 @@ static void fastrpc_context_free(struct kref *ref) for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); - if (ctx->buf) - fastrpc_buf_free(ctx->buf); + fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4); From c192569aaa68b7711b3f0d628f3d1975f83c4dba Mon Sep 17 00:00:00 2001 From: Anandu Krishnan E Date: Fri, 26 Jun 2026 21:42:48 +0530 Subject: [PATCH 0133/1058] WORKAROUND: misc: fastrpc: use dev_dbg for absent remote heap memory On platforms where remote heap memory is not present, dev_err() can flood the kernel log. Use dev_dbg() instead to reduce log verbosity in this expected condition. Signed-off-by: Anandu Krishnan E --- drivers/misc/fastrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 38ea79a47c4cf..614992f80be67 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1397,7 +1397,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, if (!cctx->remote_heap || !cctx->remote_heap->dma_addr || !cctx->remote_heap->size) { err = -ENOMEM; - dev_err(fl->sctx->dev, + dev_dbg(fl->sctx->dev, "remote heap memory region is not added\n"); return err; } From 2b0c7df2d6f6179443c63fd74cf6438bd2bdc418 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Thu, 21 May 2026 11:15:36 +0530 Subject: [PATCH 0134/1058] FROMLIST: misc: fastrpc: Move fdlist to invoke context structure The fdlist is currently part of the meta buffer which is set during fastrpc_get_args(), this fdlist is getting recalculated during fastrpc_put_args(). Move fdlist to the invoke context structure to improve maintainability and reduce redundancy. This centralizes its handling and simplifies meta buffer preparation and reading logic. Link: https://lore.kernel.org/all/20260521054539.128651-2-ekansh.gupta@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 614992f80be67..ca1d213397556 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -233,6 +233,7 @@ struct fastrpc_invoke_ctx { int pid; int client_id; u32 sc; + u64 *fdlist; u32 *crc; u64 ctxid; u64 msg_sz; @@ -1104,6 +1105,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) rpra = ctx->buf->virt; list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); pages = fastrpc_phy_page_start(list, ctx->nscalars); + ctx->fdlist = (u64 *)(pages + ctx->nscalars); args = (uintptr_t)ctx->buf->virt + metalen; rlen = pkt_size - metalen; ctx->rpra = rpra; @@ -1206,18 +1208,11 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, union fastrpc_remote_arg *rpra = ctx->rpra; struct fastrpc_user *fl = ctx->fl; struct fastrpc_map *mmap = NULL; - struct fastrpc_invoke_buf *list; - struct fastrpc_phy_page *pages; - u64 *fdlist; - int i, inbufs, outbufs, handles; + u64 *fdlist = ctx->fdlist; + int i, inbufs; int ret = 0; inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); - outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); - handles = REMOTE_SCALARS_INHANDLES(ctx->sc) + REMOTE_SCALARS_OUTHANDLES(ctx->sc); - list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); - pages = fastrpc_phy_page_start(list, ctx->nscalars); - fdlist = (uint64_t *)(pages + inbufs + outbufs + handles); for (i = inbufs; i < ctx->nbufs; ++i) { if (!ctx->maps[i]) { From 78fc88f856a6fef37d5502d14c234e1046a3bd5d Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Thu, 21 May 2026 11:15:37 +0530 Subject: [PATCH 0135/1058] FROMLIST: misc: fastrpc: Replace hardcoded ctxid mask with GENMASK Replace the hardcoded context ID mask (0xFF0) with GENMASK(11, 4) to improve readability and follow kernel bitfield conventions. Use FIELD_PREP and FIELD_GET instead of manual shifts for setting and extracting ctxid values. Link: https://lore.kernel.org/all/20260521054539.128651-3-ekansh.gupta@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index ca1d213397556..68477c047ffdc 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -23,6 +23,7 @@ #include #include #include +#include #define ADSP_DOMAIN_ID (0) #define MDSP_DOMAIN_ID (1) @@ -37,7 +38,7 @@ #define FASTRPC_CTX_MAX (256) #define FASTRPC_INIT_HANDLE 1 #define FASTRPC_DSP_UTILITIES_HANDLE 2 -#define FASTRPC_CTXID_MASK (0xFF0) +#define FASTRPC_CTXID_MASK GENMASK(11, 4) #define INIT_FILELEN_MAX (2 * 1024 * 1024) #define INIT_FILE_NAMELEN_MAX (128) #define FASTRPC_DEVICE_NAME "fastrpc" @@ -597,7 +598,7 @@ static void fastrpc_context_free(struct kref *ref) fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); - idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4); + idr_remove(&cctx->ctx_idr, FIELD_GET(FASTRPC_CTXID_MASK, ctx->ctxid)); spin_unlock_irqrestore(&cctx->lock, flags); kfree(ctx->maps); @@ -735,7 +736,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( spin_unlock_irqrestore(&cctx->lock, flags); goto err_idr; } - ctx->ctxid = ret << 4; + ctx->ctxid = FIELD_PREP(FASTRPC_CTXID_MASK, ret); spin_unlock_irqrestore(&cctx->lock, flags); kref_init(&ctx->refcount); @@ -2598,7 +2599,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, if (!cctx) return -ENODEV; - ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4); + ctxid = FIELD_GET(FASTRPC_CTXID_MASK, rsp->ctx); spin_lock_irqsave(&cctx->lock, flags); ctx = idr_find(&cctx->ctx_idr, ctxid); From 94aa751303eec02f9ae16c0d6c47e06f1b6ab86e Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Thu, 21 May 2026 11:15:38 +0530 Subject: [PATCH 0136/1058] FROMLIST: misc: fastrpc: Expand context ID mask for DSP polling mode support Current FastRPC context uses a 12-bit mask: [ID(8 bits)][PD type(4 bits)] = GENMASK(11, 4) This works for normal calls but fails for DSP polling mode. Polling mode expects a 16-bit layout: [15:8] = context ID (8 bits) [7:5] = reserved [4] = async mode bit [3:0] = PD type (4 bits) If async bit (bit 4) is set, DSP disables polling. With current mask, odd IDs can set this bit, causing DSP to skip poll updates. Update FASTRPC_CTXID_MASK to GENMASK(15, 8) so IDs occupy upper byte and lower byte is left for DSP flags and PD type. Reserved bits remain unused. This change is compatible with polling mode and does not break non-polling behavior. Bit layout: [15:8] = CCCCCCCC (context ID) [7:5] = xxx (reserved) [4] = A (async mode) [3:0] = PPPP (PD type) Link: https://lore.kernel.org/all/20260521054539.128651-4-ekansh.gupta@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 68477c047ffdc..703b34c572248 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -38,7 +38,7 @@ #define FASTRPC_CTX_MAX (256) #define FASTRPC_INIT_HANDLE 1 #define FASTRPC_DSP_UTILITIES_HANDLE 2 -#define FASTRPC_CTXID_MASK GENMASK(11, 4) +#define FASTRPC_CTXID_MASK GENMASK(15, 8) #define INIT_FILELEN_MAX (2 * 1024 * 1024) #define INIT_FILE_NAMELEN_MAX (128) #define FASTRPC_DEVICE_NAME "fastrpc" From e014e351825ea08a7a6ba61f4c005cf1aebcb147 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Thu, 21 May 2026 11:15:39 +0530 Subject: [PATCH 0137/1058] FROMLIST: misc: fastrpc: Add polling mode support for fastRPC driver For any remote call to DSP, after sending an invocation message, fastRPC driver waits for glink response and during this time the CPU can go into low power modes. This adds latency to overall fastrpc call as CPU wakeup and scheduling latencies are included. Add polling mode support with which fastRPC driver will poll continuously on a memory after sending a message to remote subsystem which will eliminate CPU wakeup and scheduling latencies and reduce fastRPC overhead. In case poll timeout happens, the call will fallback to normal RPC mode. Poll mode can be enabled by user by using FASTRPC_IOCTL_SET_OPTION ioctl request with FASTRPC_POLL_MODE request id. Link: https://lore.kernel.org/all/20260521054539.128651-5-ekansh.gupta@oss.qualcomm.com/ Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 167 ++++++++++++++++++++++++++++++++++-- include/uapi/misc/fastrpc.h | 29 +++++++ 2 files changed, 189 insertions(+), 7 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 703b34c572248..d110b69454eef 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #define ADSP_DOMAIN_ID (0) #define MDSP_DOMAIN_ID (1) @@ -38,6 +40,12 @@ #define FASTRPC_CTX_MAX (256) #define FASTRPC_INIT_HANDLE 1 #define FASTRPC_DSP_UTILITIES_HANDLE 2 +/* + * Maximum handle value for static handles. + * Static handles are pre-defined, fixed numeric values statically assigned + * in the IDL file or FastRPC framework. + */ +#define FASTRPC_MAX_STATIC_HANDLE (20) #define FASTRPC_CTXID_MASK GENMASK(15, 8) #define INIT_FILELEN_MAX (2 * 1024 * 1024) #define INIT_FILE_NAMELEN_MAX (128) @@ -106,6 +114,12 @@ #define miscdev_to_fdevice(d) container_of(d, struct fastrpc_device, miscdev) +/* Poll response number from remote processor for call completion */ +#define FASTRPC_POLL_RESPONSE (0xdecaf) + +/* Polling mode timeout limit */ +#define FASTRPC_POLL_MAX_TIMEOUT_US (10000) + struct fastrpc_phy_page { dma_addr_t addr; /* dma address */ u64 size; /* size of contiguous region */ @@ -236,8 +250,14 @@ struct fastrpc_invoke_ctx { u32 sc; u64 *fdlist; u32 *crc; + /* Poll memory that DSP updates */ + u32 *poll_addr; u64 ctxid; u64 msg_sz; + /* work done status flag */ + bool is_work_done; + /* process updates poll memory instead of glink response */ + bool is_polled; struct kref refcount; struct list_head node; /* list of ctxs */ struct completion work; @@ -265,6 +285,7 @@ struct fastrpc_soc_data { u32 sid_pos; u32 dma_addr_bits_cdsp; u32 dma_addr_bits_default; + bool poll_mode_supported; }; struct fastrpc_channel_ctx { @@ -289,6 +310,7 @@ struct fastrpc_channel_ctx { struct list_head invoke_interrupted_mmaps; bool secure; bool unsigned_support; + bool poll_mode_supported; u64 dma_mask; const struct fastrpc_soc_data *soc_data; }; @@ -312,6 +334,8 @@ struct fastrpc_user { int client_id; int pd; bool is_secure_dev; + /* Flags poll mode state */ + bool poll_mode; /* Lock for lists */ spinlock_t lock; /* lock for allocations */ @@ -1011,7 +1035,8 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) sizeof(struct fastrpc_invoke_buf) + sizeof(struct fastrpc_phy_page)) * ctx->nscalars + sizeof(u64) * FASTRPC_MAX_FDLIST + - sizeof(u32) * FASTRPC_MAX_CRCLIST; + sizeof(u32) * FASTRPC_MAX_CRCLIST + + sizeof(u32); return size; } @@ -1107,6 +1132,9 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); pages = fastrpc_phy_page_start(list, ctx->nscalars); ctx->fdlist = (u64 *)(pages + ctx->nscalars); + ctx->poll_addr = (u32 *)((uintptr_t)ctx->fdlist + sizeof(u64) * FASTRPC_MAX_FDLIST + + sizeof(u32) * FASTRPC_MAX_CRCLIST); + args = (uintptr_t)ctx->buf->virt + metalen; rlen = pkt_size - metalen; ctx->rpra = rpra; @@ -1276,6 +1304,71 @@ static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx, } +static u32 fastrpc_read_poll_addr(struct fastrpc_invoke_ctx *ctx) +{ + dma_rmb(); + return READ_ONCE(*ctx->poll_addr); +} + +static int poll_for_remote_response(struct fastrpc_invoke_ctx *ctx) +{ + u32 val; + int ret; + + /* + * Poll until DSP writes FASTRPC_POLL_RESPONSE into *ctx->poll_addr + * or until another path marks the work done. + */ + ret = read_poll_timeout_atomic(fastrpc_read_poll_addr, val, + (val == FASTRPC_POLL_RESPONSE) || ctx->is_work_done, 1, + FASTRPC_POLL_MAX_TIMEOUT_US, false, ctx); + + if (!ret && val == FASTRPC_POLL_RESPONSE) { + /* + * DSP writes FASTRPC_POLL_RESPONSE to signal successful + * completion via the poll path. + */ + ctx->is_work_done = true; + ctx->retval = 0; + } + + if (ret == -ETIMEDOUT) + ret = -EIO; + + return ret; +} + +static inline int fastrpc_wait_for_response(struct fastrpc_invoke_ctx *ctx, + u32 kernel) +{ + int err = 0; + + if (kernel) { + if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) + err = -ETIMEDOUT; + } else { + err = wait_for_completion_interruptible(&ctx->work); + } + + return err; +} + +static int fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx, + u32 kernel) +{ + int err; + + if (ctx->is_polled) { + err = poll_for_remote_response(ctx); + if (!err) + return 0; + /* If polling timed out or failed, move to normal response mode */ + ctx->is_polled = false; + } + + return fastrpc_wait_for_response(ctx, kernel); +} + static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, u32 handle, u32 sc, struct fastrpc_invoke_args *args) @@ -1311,13 +1404,14 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; - if (kernel) { - if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) - err = -ETIMEDOUT; - } else { - err = wait_for_completion_interruptible(&ctx->work); - } + /* + * Set message context as polled if the call is for a user PD + * dynamic module and user has enabled poll mode. + */ + if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD && fl->poll_mode) + ctx->is_polled = true; + err = fastrpc_wait_for_completion(ctx, kernel); if (err) goto bail; @@ -1854,6 +1948,35 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap, return 0; } +static int fastrpc_set_option(struct fastrpc_user *fl, char __user *argp) +{ + struct fastrpc_ioctl_set_option opt = {0}; + int i; + + if (copy_from_user(&opt, argp, sizeof(opt))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(opt.reserved); i++) { + if (opt.reserved[i] != 0) + return -EINVAL; + } + + if (opt.request_id != FASTRPC_POLL_MODE) + return -EINVAL; + + if (!fl->cctx->poll_mode_supported) + return -EOPNOTSUPP; + + if (opt.value == FASTRPC_POLL_MODE_ENABLE) + fl->poll_mode = true; + else if (opt.value == FASTRPC_POLL_MODE_DISABLE) + fl->poll_mode = false; + else + return -EINVAL; + + return 0; +} + static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp) { struct fastrpc_ioctl_capability cap = {0}; @@ -2215,6 +2338,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, case FASTRPC_IOCTL_MEM_UNMAP: err = fastrpc_req_mem_unmap(fl, argp); break; + case FASTRPC_IOCTL_SET_OPTION: + err = fastrpc_set_option(fl, argp); + break; case FASTRPC_IOCTL_GET_DSP_INFO: err = fastrpc_get_dsp_info(fl, argp); break; @@ -2379,6 +2505,7 @@ static const struct fastrpc_soc_data kaanapali_soc_data = { .sid_pos = 56, .dma_addr_bits_cdsp = 34, .dma_addr_bits_default = 32, + .poll_mode_supported = true, }; static const struct fastrpc_soc_data default_soc_data = { @@ -2387,6 +2514,29 @@ static const struct fastrpc_soc_data default_soc_data = { .dma_addr_bits_default = 32, }; +/* + * Exception list for older platforms that use default_soc_data but whose + * DSP firmware supports FastRPC polling mode. + * + * NOTE: This list is intentionally closed. + * Do NOT add new platforms here. New SoCs must advertise polling mode + * support via their soc_data. + */ + +static const struct of_device_id fastrpc_poll_supported_machines[] __maybe_unused = { + { .compatible = "qcom,milos" }, + { .compatible = "qcom,qcs8300" }, + { .compatible = "qcom,sa8775p" }, + { .compatible = "qcom,sar2130p" }, + { .compatible = "qcom,sm8450" }, + { .compatible = "qcom,sm8550" }, + { .compatible = "qcom,sm8650" }, + { .compatible = "qcom,sm8750" }, + { .compatible = "qcom,x1e80100" }, + { .compatible = "qcom,x1p42100" }, + {}, +}; + static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) { struct device *rdev = &rpdev->dev; @@ -2463,6 +2613,8 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); data->secure = secure_dsp; data->soc_data = soc_data; + data->poll_mode_supported = soc_data->poll_mode_supported || + of_machine_get_match(fastrpc_poll_supported_machines); switch (domain_id) { case ADSP_DOMAIN_ID: @@ -2611,6 +2763,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, } ctx->retval = rsp->retval; + ctx->is_work_done = true; complete(&ctx->work); /* diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index c6e2925f47e69..ba1ea5ed426c4 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -16,6 +16,7 @@ #define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap) +#define FASTRPC_IOCTL_SET_OPTION _IOWR('R', 12, struct fastrpc_ioctl_set_option) #define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability) /** @@ -67,6 +68,28 @@ enum fastrpc_proc_attr { /* Fastrpc attribute for memory protection of buffers */ #define FASTRPC_ATTR_SECUREMAP (1) +/** + * FASTRPC_POLL_MODE - Enable/disable poll mode for FastRPC invocations + * + * Poll mode is an optimization that allows the CPU to poll shared memory + * for completion instead of waiting for an interrupt-based response. + * This reduces latency for fast-completing operations. + * + * Restrictions: + * - Only supported for USER_PD (User Protection Domain) + * - Only applies to dynamic modules (handle > 20) + * - Static modules always use interrupt-based completion + * + * Values: + * - 0: Disable poll mode (use interrupt-based completion) + * - 1: Enable poll mode (poll shared memory for completion) + */ +#define FASTRPC_POLL_MODE (1) + +/* Values for FASTRPC_POLL_MODE request */ +#define FASTRPC_POLL_MODE_DISABLE 0 +#define FASTRPC_POLL_MODE_ENABLE 1 + struct fastrpc_invoke_args { __u64 ptr; __u64 length; @@ -133,6 +156,12 @@ struct fastrpc_mem_unmap { __s32 reserved[5]; }; +struct fastrpc_ioctl_set_option { + __u32 request_id; /* Request type (e.g., FASTRPC_POLL_MODE) */ + __u32 value; /* Request-specific value */ + __s32 reserved[6]; +}; + struct fastrpc_ioctl_capability { __u32 unused; /* deprecated, ignored by the kernel */ __u32 attribute_id; From ba80c9c5409823c55d75667ce6162982329d9b2d Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 12 Mar 2026 19:53:06 +0530 Subject: [PATCH 0138/1058] FROMLIST: ASoC: codecs: lpass-wsa-macro: Switch to PM clock framework for runtime PM Convert the LPASS WSA macro codec driver to use the PM clock framework for runtime power management. The driver now relies on pm_clk helpers and runtime PM instead of manually enabling and disabling macro, dcodec, mclk, npl, and fsgen clocks. Runtime suspend and resume handling is delegated to the PM core via pm_clk_suspend() and pm_clk_resume(), while existing runtime PM callbacks continue to manage regcache state. This ensures clocks are enabled only when the WSA macro is active, improves power efficiency on LPASS platforms supporting LPI/island modes, and aligns the driver with common ASoC runtime PM patterns used across Qualcomm LPASS codec drivers. Link: https://lore.kernel.org/all/20260413121824.375473-2-ajay.nandam@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam --- sound/soc/codecs/lpass-wsa-macro.c | 118 +++++++++-------------------- 1 file changed, 37 insertions(+), 81 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 5ad0448af649d..6aa6c4d959c04 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "lpass-macro-common.h" @@ -2529,15 +2530,15 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = { static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) { struct regmap *regmap = wsa->regmap; + int ret; - if (enable) { - int ret; + ret = pm_runtime_get_sync(wsa->dev); + if (ret < 0) { + pm_runtime_put_noidle(wsa->dev); + return ret; + } - ret = clk_prepare_enable(wsa->mclk); - if (ret) { - dev_err(wsa->dev, "failed to enable mclk\n"); - return ret; - } + if (enable) { wsa_macro_mclk_enable(wsa, true); regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, @@ -2548,9 +2549,10 @@ static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, CDC_WSA_SWR_CLK_EN_MASK, 0); wsa_macro_mclk_enable(wsa, false); - clk_disable_unprepare(wsa->mclk); } + pm_runtime_mark_last_busy(wsa->dev); + pm_runtime_put_autosuspend(wsa->dev); return 0; } @@ -2774,25 +2776,23 @@ static int wsa_macro_probe(struct platform_device *pdev) clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); - ret = clk_prepare_enable(wsa->macro); + ret = devm_pm_clk_create(dev); if (ret) - goto err; + return ret; - ret = clk_prepare_enable(wsa->dcodec); - if (ret) - goto err_dcodec; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; - ret = clk_prepare_enable(wsa->mclk); - if (ret) - goto err_mclk; + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); - ret = clk_prepare_enable(wsa->npl); - if (ret) - goto err_npl; - ret = clk_prepare_enable(wsa->fsgen); - if (ret) - goto err_fsgen; + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + goto err_rpm_disable; + } /* reset swr ip */ regmap_update_bits(wsa->regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, @@ -2809,44 +2809,26 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_macro_dai, ARRAY_SIZE(wsa_macro_dai)); if (ret) - goto err_clkout; - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = wsa_macro_register_mclk_output(wsa); if (ret) - goto err_clkout; + goto err_rpm_put; - return 0; + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); -err_clkout: - clk_disable_unprepare(wsa->fsgen); -err_fsgen: - clk_disable_unprepare(wsa->npl); -err_npl: - clk_disable_unprepare(wsa->mclk); -err_mclk: - clk_disable_unprepare(wsa->dcodec); -err_dcodec: - clk_disable_unprepare(wsa->macro); -err: + return 0; +err_rpm_put: + pm_runtime_put_noidle(dev); +err_rpm_disable: + pm_runtime_disable(dev); return ret; - } static void wsa_macro_remove(struct platform_device *pdev) { - struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(wsa->macro); - clk_disable_unprepare(wsa->dcodec); - clk_disable_unprepare(wsa->mclk); - clk_disable_unprepare(wsa->npl); - clk_disable_unprepare(wsa->fsgen); + pm_runtime_disable(&pdev->dev); } static int wsa_macro_runtime_suspend(struct device *dev) @@ -2856,11 +2838,7 @@ static int wsa_macro_runtime_suspend(struct device *dev) regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - clk_disable_unprepare(wsa->fsgen); - clk_disable_unprepare(wsa->npl); - clk_disable_unprepare(wsa->mclk); - - return 0; + return pm_clk_suspend(dev); } static int wsa_macro_runtime_resume(struct device *dev) @@ -2868,34 +2846,12 @@ static int wsa_macro_runtime_resume(struct device *dev) struct wsa_macro *wsa = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(wsa->mclk); - if (ret) { - dev_err(dev, "unable to prepare mclk\n"); - return ret; - } - - ret = clk_prepare_enable(wsa->npl); - if (ret) { - dev_err(dev, "unable to prepare mclkx2\n"); - goto err_npl; - } - - ret = clk_prepare_enable(wsa->fsgen); - if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; - } - regcache_cache_only(wsa->regmap, false); - regcache_sync(wsa->regmap); - - return 0; -err_fsgen: - clk_disable_unprepare(wsa->npl); -err_npl: - clk_disable_unprepare(wsa->mclk); + ret = pm_clk_resume(dev); + if (ret) + return ret; - return ret; + return regcache_sync(wsa->regmap); } static const struct dev_pm_ops wsa_macro_pm_ops = { From 866296c145e712ad5d68db7beee10ea042826078 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 12 Mar 2026 19:46:37 +0530 Subject: [PATCH 0139/1058] FROMLIST: ASoC: codecs: lpass-va-macro: Switch to PM clock framework for runtime PM Convert the LPASS VA macro codec driver to use the PM clock framework for runtime power management. The driver now relies on pm_clk helpers and runtime PM instead of manually enabling and disabling macro, dcodec, mclk, and npl clocks. All clock control during runtime suspend and resume is delegated to the PM core via pm_clk_suspend() and pm_clk_resume(). This change ensures clocks are only enabled when the VA macro is active, improves power efficiency on LPASS platforms supporting LPI/island modes, and aligns the driver with common ASoC runtime PM patterns used across Qualcomm LPASS codec drivers. Link: https://lore.kernel.org/all/20260413121824.375473-3-ajay.nandam@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam --- sound/soc/codecs/lpass-va-macro.c | 120 ++++++++++++++---------------- 1 file changed, 54 insertions(+), 66 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 528d5b167ecff..b909f8befa10e 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1348,18 +1349,22 @@ static int fsgen_gate_enable(struct clk_hw *hw) struct regmap *regmap = va->regmap; int ret; - if (va->has_swr_master) { - ret = clk_prepare_enable(va->mclk); - if (ret) - return ret; + ret = pm_runtime_get_sync(va->dev); + if (ret < 0) { + pm_runtime_put_noidle(va->dev); + return ret; } ret = va_macro_mclk_enable(va, true); + if (ret) { + pm_runtime_put_noidle(va->dev); + return ret; + } if (va->has_swr_master) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, CDC_VA_SWR_CLK_EN_MASK, CDC_VA_SWR_CLK_ENABLE); - return ret; + return 0; } static void fsgen_gate_disable(struct clk_hw *hw) @@ -1372,8 +1377,24 @@ static void fsgen_gate_disable(struct clk_hw *hw) CDC_VA_SWR_CLK_EN_MASK, 0x0); va_macro_mclk_enable(va, false); - if (va->has_swr_master) - clk_disable_unprepare(va->mclk); + + pm_runtime_mark_last_busy(va->dev); + pm_runtime_put_autosuspend(va->dev); +} + +static int va_macro_setup_pm_clocks(struct device *dev, struct va_macro *va) +{ + int ret; + + ret = devm_pm_clk_create(dev); + if (ret) + return ret; + + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; + + return 0; } static int fsgen_gate_is_enabled(struct clk_hw *hw) @@ -1534,6 +1555,7 @@ static int va_macro_probe(struct platform_device *pdev) void __iomem *base; u32 sample_rate = 0; int ret; + int rpm_ret; va = devm_kzalloc(dev, sizeof(*va), GFP_KERNEL); if (!va) @@ -1601,22 +1623,18 @@ static int va_macro_probe(struct platform_device *pdev) clk_set_rate(va->npl, 2 * VA_MACRO_MCLK_FREQ); } - ret = clk_prepare_enable(va->macro); - if (ret) - goto err; - - ret = clk_prepare_enable(va->dcodec); + ret = va_macro_setup_pm_clocks(dev, va); if (ret) - goto err_dcodec; + goto err_rpm_disable; - ret = clk_prepare_enable(va->mclk); - if (ret) - goto err_mclk; + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); - if (va->has_npl_clk) { - ret = clk_prepare_enable(va->npl); - if (ret) - goto err_npl; + rpm_ret = pm_runtime_resume_and_get(dev); + if (rpm_ret < 0) { + ret = rpm_ret; + goto err_rpm_disable; } /** @@ -1629,7 +1647,7 @@ static int va_macro_probe(struct platform_device *pdev) /* read version from register */ ret = va_macro_set_lpass_codec_version(va); if (ret) - goto err_clkout; + goto err_rpm_put; } if (va->has_swr_master) { @@ -1659,35 +1677,27 @@ static int va_macro_probe(struct platform_device *pdev) va_macro_dais, ARRAY_SIZE(va_macro_dais)); if (ret) - goto err_clkout; - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = va_macro_register_fsgen_output(va); if (ret) - goto err_clkout; + goto err_rpm_put; va->fsgen = devm_clk_hw_get_clk(dev, &va->hw, "fsgen"); if (IS_ERR(va->fsgen)) { ret = PTR_ERR(va->fsgen); - goto err_clkout; + goto err_rpm_put; } + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; -err_clkout: - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); -err_npl: - clk_disable_unprepare(va->mclk); -err_mclk: - clk_disable_unprepare(va->dcodec); -err_dcodec: - clk_disable_unprepare(va->macro); +err_rpm_put: + pm_runtime_put_noidle(dev); +err_rpm_disable: + pm_runtime_disable(dev); err: lpass_macro_pds_exit(va->pds); @@ -1698,12 +1708,7 @@ static void va_macro_remove(struct platform_device *pdev) { struct va_macro *va = dev_get_drvdata(&pdev->dev); - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); - - clk_disable_unprepare(va->mclk); - clk_disable_unprepare(va->dcodec); - clk_disable_unprepare(va->macro); + pm_runtime_disable(&pdev->dev); lpass_macro_pds_exit(va->pds); } @@ -1715,12 +1720,7 @@ static int va_macro_runtime_suspend(struct device *dev) regcache_cache_only(va->regmap, true); regcache_mark_dirty(va->regmap); - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); - - clk_disable_unprepare(va->mclk); - - return 0; + return pm_clk_suspend(dev); } static int va_macro_runtime_resume(struct device *dev) @@ -1728,25 +1728,13 @@ static int va_macro_runtime_resume(struct device *dev) struct va_macro *va = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(va->mclk); - if (ret) { - dev_err(va->dev, "unable to prepare mclk\n"); + ret = pm_clk_resume(dev); + if (ret) return ret; - } - - if (va->has_npl_clk) { - ret = clk_prepare_enable(va->npl); - if (ret) { - clk_disable_unprepare(va->mclk); - dev_err(va->dev, "unable to prepare npl\n"); - return ret; - } - } regcache_cache_only(va->regmap, false); - regcache_sync(va->regmap); - return 0; + return regcache_sync(va->regmap); } From 69edcd2880bf252f0c251e13a14a5e7448c14be6 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Fri, 10 Apr 2026 17:01:17 +0530 Subject: [PATCH 0140/1058] FROMLIST: ASoC: codecs: lpass-wsa-macro: Guard optional NPL clock rate programming The NPL clock is only present on some platforms. When it is absent, wsa->npl remains NULL, but the driver unconditionally programs its rate. Guard clk_set_rate() for the NPL clock so platforms without NPL do not attempt to access it. No functional change on platforms that provide the NPL clock. Link: https://lore.kernel.org/all/20260413121824.375473-4-ajay.nandam@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam --- sound/soc/codecs/lpass-wsa-macro.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 6aa6c4d959c04..8c8c50a63f4e2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2774,7 +2774,8 @@ static int wsa_macro_probe(struct platform_device *pdev) /* set MCLK and NPL rates */ clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); - clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); + if (wsa->npl) + clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); ret = devm_pm_clk_create(dev); if (ret) From 5434c3273781dc09ed25187beb7b7055e24f694c Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 8 Jun 2026 14:11:38 +0530 Subject: [PATCH 0141/1058] FROMLIST: soc: qcom: pd-mapper: Add support for SA8775P Add support for the Qualcomm SA8775P SoC to the protection domain mapper. SA8775P share the same protection domain configuration as SC8280XP with an additional gpdsp domain, except for charger_pd. Add an entry to the kernel, to avoid the need for userspace to provide this service. Link: https://lore.kernel.org/all/20260608084139.1468000-2-mohammad.rafi.shaik@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mohammad Rafi Shaik --- drivers/soc/qcom/qcom_pd_mapper.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index b99718e25f2fc..03a5a3a73719e 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -311,6 +311,24 @@ static const struct qcom_pdm_domain_data cdsp_root_pd = { .services = { NULL }, }; +static const struct qcom_pdm_domain_data cdsp1_root_pd = { + .domain = "msm/cdsp1/root_pd", + .instance_id = 125, + .services = { NULL }, +}; + +static const struct qcom_pdm_domain_data gpdsp_root_pd = { + .domain = "msm/gpdsp/root_pd", + .instance_id = 192, + .services = { NULL }, +}; + +static const struct qcom_pdm_domain_data gpdsp1_root_pd = { + .domain = "msm/gpdsp1/root_pd", + .instance_id = 241, + .services = { NULL }, +}; + static const struct qcom_pdm_domain_data slpi_root_pd = { .domain = "msm/slpi/root_pd", .instance_id = 90, @@ -426,6 +444,16 @@ static const struct qcom_pdm_domain_data *qcs615_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *sa8775p_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &cdsp_root_pd, + &cdsp1_root_pd, + &gpdsp_root_pd, + &gpdsp1_root_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sc7180_domains[] = { &adsp_audio_pd, &adsp_root_pd_pdr, @@ -603,6 +631,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, { .compatible = "qcom,qcs615", .data = qcs615_domains, }, + { .compatible = "qcom,sa8775p", .data = sa8775p_domains, }, { .compatible = "qcom,sc7180", .data = sc7180_domains, }, { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, From d07617f15a39cb944bbc2c0c8bb5aaebd335be82 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 8 Jun 2026 14:11:39 +0530 Subject: [PATCH 0142/1058] FROMLIST: soc: qcom: pd-mapper: Add support for QCS8300 Add support for the Qualcomm QCS8300 SoC to the protection domain mapper. QCS8300 share the same protection domain configuration as SC8280XP, except charger_pd. Add an entry to the kernel, to avoid the need for userspace to provide this service. Link: https://lore.kernel.org/all/20260608084139.1468000-3-mohammad.rafi.shaik@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mohammad Rafi Shaik --- drivers/soc/qcom/qcom_pd_mapper.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 03a5a3a73719e..d98c6df52bea2 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -444,6 +444,14 @@ static const struct qcom_pdm_domain_data *qcs615_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *qcs8300_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &cdsp_root_pd, + &gpdsp_root_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sa8775p_domains[] = { &adsp_audio_pd, &adsp_root_pd, @@ -631,6 +639,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, { .compatible = "qcom,qcs615", .data = qcs615_domains, }, + { .compatible = "qcom,qcs8300", .data = qcs8300_domains, }, { .compatible = "qcom,sa8775p", .data = sa8775p_domains, }, { .compatible = "qcom,sc7180", .data = sc7180_domains, }, { .compatible = "qcom,sc7280", .data = sc7280_domains, }, From e3645d5138765fce372be8c193723031a501533d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Sun, 7 Jun 2026 02:58:19 +0800 Subject: [PATCH 0143/1058] FROMLIST: ASoC: qcom: qdsp6: q6prm: add the missing MCLK clock IDs Add the missing MCLK ids for the q6prm DSP interface. Link: https://lore.kernel.org/all/20260607-rubikpi-next-20260605-v1-3-7f334e16fea6@thundersoft.com/ Reviewed-by: Srinivas Kandagatla Signed-off-by: Neil Armstrong --- sound/soc/qcom/qdsp6/q6prm-clocks.c | 5 +++++ sound/soc/qcom/qdsp6/q6prm.h | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/qcom/qdsp6/q6prm-clocks.c b/sound/soc/qcom/qdsp6/q6prm-clocks.c index 4c574b48ab004..51b131fa95316 100644 --- a/sound/soc/qcom/qdsp6/q6prm-clocks.c +++ b/sound/soc/qcom/qdsp6/q6prm-clocks.c @@ -42,6 +42,11 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_1), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_2), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_3), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_4), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_5), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), Q6PRM_CLK(LPASS_CLK_ID_VA_CORE_MCLK), diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/q6prm.h index a988a32086fe1..6917e70bcb8a5 100644 --- a/sound/soc/qcom/qdsp6/q6prm.h +++ b/sound/soc/qcom/qdsp6/q6prm.h @@ -52,6 +52,17 @@ /* Clock ID for QUINARY MI2S OSR CLK */ #define Q6PRM_LPASS_CLK_ID_QUI_MI2S_OSR 0x116 +/* Clock ID for MCLK1 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_1 0x300 +/* Clock ID for MCLK2 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_2 0x301 +/* Clock ID for MCLK3 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_3 0x302 +/* Clock ID for MCLK4 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_4 0x303 +/* Clock ID for MCLK5 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_5 0x304 + #define Q6PRM_LPASS_CLK_ID_WSA_CORE_MCLK 0x305 #define Q6PRM_LPASS_CLK_ID_WSA_CORE_NPL_MCLK 0x306 From 9e68c57d3e0beae93eac301a77d2ee90edad021c Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 29 Jun 2026 19:46:32 +0530 Subject: [PATCH 0144/1058] FROMLIST: ASoC: qcom: sdm845: skip set_channel_map for SDW stream DAIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On sdm845 the SLIM Playback backend lists wcd934x alongside the qcom SoundWire master and its SWR slave speaker codecs as codec DAIs on the same link. sdm845_dai_init() was calling set_channel_map with hardcoded wcd934x SLIM channel numbers for every codec DAI on that link, including the SoundWire ones, corrupting their channel configuration. Skip set_channel_map for any DAI that implements .set_stream, as that op is the distinguishing marker of DAIs that own an SDW stream path — both the qcom SWR master and SWR slave codecs register it, while wcd934x does not. This confines the SLIM channel map to wcd934x where it belongs. Link: https://lore.kernel.org/all/20260629141633.86657-2-mohammad.rafi.shaik@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sdm845.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 0ce9dff4dc525..509d7a551397e 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -294,13 +294,26 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { - rval = snd_soc_dai_set_channel_map(codec_dai, - ARRAY_SIZE(tx_ch), - tx_ch, - ARRAY_SIZE(rx_ch), - rx_ch); - if (rval != 0 && rval != -ENOTSUPP) - return rval; + component = codec_dai->component; + + if (!component || !component->dev) + continue; + + /* + * Only wcd934x (SLIM codec) needs these static channel maps. + * DAIs that own an SDW stream — the qcom SWR master and SWR + * slave speaker codecs — implement .set_stream; skip them. + */ + if (!codec_dai->driver || !codec_dai->driver->ops || + !codec_dai->driver->ops->set_stream) { + rval = snd_soc_dai_set_channel_map(codec_dai, + ARRAY_SIZE(tx_ch), + tx_ch, + ARRAY_SIZE(rx_ch), + rx_ch); + if (rval != 0 && rval != -ENOTSUPP) + return rval; + } snd_soc_dai_set_sysclk(codec_dai, 0, WCD934X_DEFAULT_MCLK_RATE, From 88b8f29570c5211e654cec357e6a1282f92737b7 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 29 Jun 2026 19:46:33 +0530 Subject: [PATCH 0145/1058] FROMLIST: soundwire: qcom: Add set_channel_map support to SWR master DAI Add .set_channel_map support to the SWR master DAI so the ASoC layer can program per-port channel masks used by port_enable(). Fix several issues in channel map handling: clip programming to available ports to avoid out-of-bounds access, use 1-based port indexing, and store TX/RX masks separately. Also track per-direction validity and select the effective mask based on port role to avoid incorrect precedence and ensure full-width masks are preserved. Fall back to the SDW stream-provided channel mask when no mapping is configured, preserving existing behaviour. Link: https://lore.kernel.org/all/20260629141633.86657-3-mohammad.rafi.shaik@oss.qualcomm.com/ Fixes: 7796c97df6b1 ("soundwire: qcom: Add set_channel_map api support") Reported-by: Yongqin Liu Closes: https://lore.kernel.org/all/4ddd6855-3817-4dc4-81c4-d8ddaa039865@oss.qualcomm.com/ Reported-by: Jie Gan Closes: https://lore.kernel.org/all/CAMSo37U1kJq_gK8jiW9iMbhHXtn=Chr7NawiK4fPUPj4kyqH2w@mail.gmail.com/ Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/33fe8fe7-719a-405a-9ed2-d9f816ce1d57@sabinyo.mountain/ Signed-off-by: Mohammad Rafi Shaik --- drivers/soundwire/qcom.c | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 3d8f5a81eff19..e63736e824780 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -160,6 +160,10 @@ struct qcom_swrm_port_config { u8 word_length; u8 blk_group_count; u8 lane_control; + u8 tx_ch_mask; + u8 rx_ch_mask; + bool tx_ch_map_valid; + bool rx_ch_map_valid; }; /* @@ -1109,12 +1113,28 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus, { u32 reg; struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + struct qcom_swrm_port_config *pcfg; u32 val; u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK]; reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank); ctrl->reg_read(ctrl, reg, &val); + pcfg = &ctrl->pconfig[enable_ch->port_num]; + + mutex_lock(&ctrl->port_lock); + if (enable_ch->port_num <= ctrl->num_dout_ports) { + if (pcfg->rx_ch_map_valid) + enable_ch->ch_mask = pcfg->rx_ch_mask; + else if (pcfg->tx_ch_map_valid) + enable_ch->ch_mask = pcfg->tx_ch_mask; + } else { + if (pcfg->tx_ch_map_valid) + enable_ch->ch_mask = pcfg->tx_ch_mask; + else if (pcfg->rx_ch_map_valid) + enable_ch->ch_mask = pcfg->rx_ch_mask; + } + mutex_unlock(&ctrl->port_lock); if (enable_ch->enable) val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); @@ -1334,6 +1354,39 @@ static void *qcom_swrm_get_sdw_stream(struct snd_soc_dai *dai, int direction) return ctrl->sruntime[dai->id]; } +static int qcom_swrm_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + unsigned int max_ports = ctrl->nports; + unsigned int i; + + if ((tx_num && !tx_slot) || (rx_num && !rx_slot)) + return -EINVAL; + + mutex_lock(&ctrl->port_lock); + for (i = 1; i <= max_ports; i++) { + ctrl->pconfig[i].tx_ch_map_valid = false; + ctrl->pconfig[i].rx_ch_map_valid = false; + + /* TX setup */ + if (tx_slot && i < tx_num) { + ctrl->pconfig[i].tx_ch_mask = tx_slot[i]; + ctrl->pconfig[i].tx_ch_map_valid = true; + } + + /* RX setup */ + if (rx_slot && i < rx_num) { + ctrl->pconfig[i].rx_ch_mask = rx_slot[i]; + ctrl->pconfig[i].rx_ch_map_valid = true; + } + } + mutex_unlock(&ctrl->port_lock); + + return 0; +} + static int qcom_swrm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -1370,6 +1423,7 @@ static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = { .shutdown = qcom_swrm_shutdown, .set_stream = qcom_swrm_set_sdw_stream, .get_stream = qcom_swrm_get_sdw_stream, + .set_channel_map = qcom_swrm_set_channel_map, }; static const struct snd_soc_component_driver qcom_swrm_dai_component = { From e84704bd07cbb43835d43eddcd64a38477da9a01 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 14 May 2026 19:55:54 +0530 Subject: [PATCH 0146/1058] FROMLIST: arm64: dts: qcom: Add psci reboot-modes for talos boards Add PSCI SYSTEM_RESET2 reboot-modes for qcs615-ride, for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Support for these modes is firmware dependent. Link: https://lore.kernel.org/all/20260514-arm-psci-system_reset2-vendor-reboots-v22-13-28a5bde07483@oss.qualcomm.com/ Reviewed-by: Bartosz Golaszewski Signed-off-by: Song Xue Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 7 +++++++ arch/arm64/boot/dts/qcom/talos.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 51b13b492472f..4ecc2c2dbbe92 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -510,6 +510,13 @@ }; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &qupv3_id_0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index fb1bbc51bb8a4..312c7bece5f12 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -580,7 +580,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From 3a0be2146eb09d6faeb9a79172ac63436e58dfb9 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Mon, 27 Apr 2026 23:56:05 +0530 Subject: [PATCH 0147/1058] FROMLIST: arm64: dts: qcom: talos-evk-som: Enable Adreno 612 GPU Enable GPU for talos-evk-som platform and provide path for zap shader. Link: https://lore.kernel.org/all/20260427-talos-evt-gpu-v1-1-d40b6dffa108@oss.qualcomm.com/ Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen --- arch/arm64/boot/dts/qcom/talos-evk-som.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi index 294354c034c37..6d2cff3cf23cc 100644 --- a/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi @@ -317,6 +317,14 @@ status = "okay"; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs615/a612_zap.mbn"; +}; + &i2c5 { clock-frequency = <400000>; status = "okay"; From 821972c82835f28188f55d05b77e90117ecbaf82 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Tue, 26 May 2026 16:26:09 +0530 Subject: [PATCH 0148/1058] FROMLIST: iio: adc: qcom-spmi-adc5-gen3: Share SDAM0 IRQ with ADC_TM auxiliary driver The SDAM0 IRQ can be triggered for both EOC (end of conversion) events for immediate ADC reads done in this driver and for threshold violation events, based on ADC_TM thresholds configured from the auxiliary ADC_TM driver on TM channels on the first SDAM. At present, this interrupt is handled only in the ISR in the main ADC driver. When the ISR is triggered for an ADC_TM event, this driver notifies the ADC_TM driver by calling a notifier callback exposed from it for this purpose. To simplify the interrupt handling in both drivers, share the interrupt between the drivers. With this, ADC_TM interrupts on SDAM0 will be handled directly in the ADC_TM driver, so remove the notifier callback and all TM interrupt handling in the main ADC ISR. Link: https://lore.kernel.org/all/20260526-gen3_adc_tm-v2-1-702fbac919ac@oss.qualcomm.com/ Reviewed-by: Jonathan Cameron Signed-off-by: Jishnu Prakash --- drivers/iio/adc/qcom-spmi-adc5-gen3.c | 66 ++++++------------- include/linux/iio/adc/qcom-adc5-gen3-common.h | 2 - 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index 48c793b18d11e..f354532a17f0c 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -56,9 +56,6 @@ struct adc5_channel_prop { * requests from multiple clients. * @data: software configuration data. * @n_tm_channels: number of ADC channels used for TM measurements. - * @handler: TM callback to be called for threshold violation interrupt - * on first SDAM. - * @tm_aux: pointer to auxiliary TM device. */ struct adc5_chip { struct device *dev; @@ -70,8 +67,6 @@ struct adc5_chip { struct mutex lock; const struct adc5_data *data; unsigned int n_tm_channels; - void (*handler)(struct auxiliary_device *tm_aux); - struct auxiliary_device *tm_aux; }; int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index, @@ -287,23 +282,21 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) { struct adc5_chip *adc = dev_id; struct device *dev = adc->dev; - struct auxiliary_device *adev; u8 status, eoc_status, val; - u8 tm_status[2]; int ret; ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_STATUS1, &status, sizeof(status)); if (ret) { dev_err(dev, "adc read status1 failed with %d\n", ret); - return IRQ_HANDLED; + return IRQ_NONE; } ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_EOC_STS, &eoc_status, sizeof(eoc_status)); if (ret) { dev_err(dev, "adc read eoc status failed with %d\n", ret); - return IRQ_HANDLED; + return IRQ_NONE; } if (status & ADC5_GEN3_STATUS1_CONV_FAULT) { @@ -316,30 +309,13 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) return IRQ_HANDLED; } - /* CHAN0 is the preconfigured channel for immediate conversion */ - if (eoc_status & ADC5_GEN3_EOC_CHAN_0) - complete(&adc->complete); - - ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, - ADC5_GEN3_TM_HIGH_STS, tm_status, sizeof(tm_status)); - if (ret) { - dev_err(dev, "adc read TM status failed with %d\n", ret); - return IRQ_HANDLED; - } - - dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n", - status, eoc_status, tm_status[0], tm_status[1]); + dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x\n", status, eoc_status); - if (tm_status[0] || tm_status[1]) { - adev = adc->tm_aux; - if (!adev || !adev->dev.driver) { - dev_err(dev, "adc_tm auxiliary device not initialized\n"); - return IRQ_HANDLED; - } - - adc->handler(adev); - } + /* CHAN0 is the preconfigured channel for immediate conversion */ + if (!(eoc_status & ADC5_GEN3_EOC_CHAN_0)) + return IRQ_NONE; + complete(&adc->complete); return IRQ_HANDLED; } @@ -684,8 +660,6 @@ static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc) if (ret) return ret; - adc->tm_aux = &aux_device->aux_dev; - return 0; } @@ -741,16 +715,6 @@ int adc5_gen3_therm_code_to_temp(struct device *dev, } EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3"); -void adc5_gen3_register_tm_event_notifier(struct device *dev, - void (*handler)(struct auxiliary_device *)) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); - struct adc5_chip *adc = iio_priv(indio_dev); - - adc->handler = handler; -} -EXPORT_SYMBOL_NS_GPL(adc5_gen3_register_tm_event_notifier, "QCOM_SPMI_ADC5_GEN3"); - static int adc5_gen3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -817,10 +781,18 @@ static int adc5_gen3_probe(struct platform_device *pdev) return -ENOMEM; } - ret = devm_request_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq, - adc5_gen3_isr, 0, - adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name, - adc); + /* + * This interrupt is shared with the ADC_TM auxiliary driver, which + * is threaded and uses IRQF_ONESHOT. Since shared interrupts need + * to agree on IRQF_ONESHOT configuration and there is a kernel + * warning for using IRQF_ONESHOT with non-threaded interrupts, + * make this also a threaded IRQ. + */ + + ret = devm_request_threaded_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq, + NULL, adc5_gen3_isr, IRQF_ONESHOT | IRQF_SHARED, + adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name, + adc); if (ret) return dev_err_probe(dev, ret, "Failed to request SDAM%d irq\n", diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h index 6303eaa6640be..39cbfcbdb101c 100644 --- a/include/linux/iio/adc/qcom-adc5-gen3-common.h +++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h @@ -205,7 +205,5 @@ int adc5_gen3_get_scaled_reading(struct device *dev, int adc5_gen3_therm_code_to_temp(struct device *dev, struct adc5_channel_common_prop *common_props, u16 code, int *val); -void adc5_gen3_register_tm_event_notifier(struct device *dev, - void (*handler)(struct auxiliary_device *)); #endif /* QCOM_ADC5_GEN3_COMMON_H */ From 49e9e5097e0f01b91ab60ed65ebbf534eabdadf1 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Tue, 26 May 2026 16:26:10 +0530 Subject: [PATCH 0149/1058] FROMLIST: thermal: qcom: add support for PMIC5 Gen3 ADC thermal monitoring Add support for ADC_TM part of PMIC5 Gen3. This is an auxiliary driver under the Gen3 ADC driver, which implements the threshold setting and interrupt generating functionalities of QCOM ADC_TM drivers, used to support thermal trip points. Link: https://lore.kernel.org/all/20260526-gen3_adc_tm-v2-2-702fbac919ac@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- drivers/thermal/qcom/Kconfig | 9 + drivers/thermal/qcom/Makefile | 1 + drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c | 437 ++++++++++++++++++ 3 files changed, 447 insertions(+) create mode 100644 drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig index a6bb01082ec69..1acb11e4ac800 100644 --- a/drivers/thermal/qcom/Kconfig +++ b/drivers/thermal/qcom/Kconfig @@ -21,6 +21,15 @@ config QCOM_SPMI_ADC_TM5 Thermal client sets threshold temperature for both warm and cool and gets updated when a threshold is reached. +config QCOM_SPMI_ADC_TM5_GEN3 + tristate "Qualcomm SPMI PMIC Thermal Monitor ADC5 Gen3" + depends on QCOM_SPMI_ADC5_GEN3 + help + This enables the auxiliary thermal driver for the ADC5 Gen3 thermal + monitoring device. It shows up as a thermal zone with multiple trip points. + Thermal client sets threshold temperature for both warm and cool and + gets updated when a threshold is reached. + config QCOM_SPMI_TEMP_ALARM tristate "Qualcomm SPMI PMIC Temperature Alarm" depends on OF && SPMI && IIO diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 0fa2512042e78..828d9e7bc7970 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o qcom_tsens-y += tsens.o tsens-v2.o tsens-v1.o tsens-v0_1.o \ tsens-8960.o obj-$(CONFIG_QCOM_SPMI_ADC_TM5) += qcom-spmi-adc-tm5.o +obj-$(CONFIG_QCOM_SPMI_ADC_TM5_GEN3) += qcom-spmi-adc-tm5-gen3.o obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o obj-$(CONFIG_QCOM_LMH) += lmh.o diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c new file mode 100644 index 0000000000000..633008f173a8a --- /dev/null +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../thermal_hwmon.h" + +#define ADC_TM5_GEN3_CONFIG_REGS 12 + +struct device; +struct adc_tm5_gen3_chip; + +/** + * struct adc_tm5_gen3_channel_props - ADC_TM channel structure + * @timer: time period of recurring TM measurement. + * @tm_chan_index: TM channel number used (ranging from 1-7). + * @sdam_index: SDAM on which this TM channel lies. + * @common_props: structure with common ADC channel properties. + * @high_thr_en: TM high threshold crossing detection enabled. + * @low_thr_en: TM low threshold crossing detection enabled. + * @chip: ADC TM device. + * @tzd: pointer to thermal device corresponding to TM channel. + */ +struct adc_tm5_gen3_channel_props { + unsigned int timer; + unsigned int tm_chan_index; + unsigned int sdam_index; + struct adc5_channel_common_prop common_props; + bool high_thr_en; + bool low_thr_en; + struct adc_tm5_gen3_chip *chip; + struct thermal_zone_device *tzd; +}; + +/** + * struct adc_tm5_gen3_chip - ADC Thermal Monitoring device structure + * @dev_data: Top-level ADC device data. + * @chan_props: Array of ADC_TM channel structures. + * @nchannels: number of TM channels allocated + * @dev: SPMI ADC5 Gen3 device. + */ +struct adc_tm5_gen3_chip { + struct adc5_device_data *dev_data; + struct adc_tm5_gen3_channel_props *chan_props; + unsigned int nchannels; + struct device *dev; +}; + +DEFINE_GUARD(adc5_gen3, struct adc_tm5_gen3_chip *, adc5_gen3_mutex_lock(_T->dev), + adc5_gen3_mutex_unlock(_T->dev)) + +static int get_sdam_from_irq(struct adc_tm5_gen3_chip *adc_tm5, int irq) +{ + for (int i = 0; i < adc_tm5->dev_data->num_sdams; i++) { + if (adc_tm5->dev_data->base[i].irq == irq) + return i; + } + return -ENOENT; +} + +static irqreturn_t adctm5_gen3_isr(int irq, void *dev_id) +{ + struct adc_tm5_gen3_chip *adc_tm5 = dev_id; + int ret, sdam_num; + u8 tm_status[2]; + u8 status, val; + + sdam_num = get_sdam_from_irq(adc_tm5, irq); + if (sdam_num < 0) + return IRQ_NONE; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_STATUS1, + &status, sizeof(status)); + if (ret) + return IRQ_NONE; + + if (status & ADC5_GEN3_STATUS1_CONV_FAULT) { + val = ADC5_GEN3_CONV_ERR_CLR_REQ; + adc5_gen3_status_clear(adc_tm5->dev_data, sdam_num, + ADC5_GEN3_CONV_ERR_CLR, &val, 1); + return IRQ_HANDLED; + } + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_TM_HIGH_STS, + tm_status, sizeof(tm_status)); + if (ret) + return IRQ_NONE; + + if (tm_status[0] || tm_status[1]) + return IRQ_WAKE_THREAD; + + return IRQ_NONE; +} + +static int adc5_gen3_tm_status_check(struct adc_tm5_gen3_chip *adc_tm5, + int sdam_index, u8 *tm_status, u8 *buf) +{ + int ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_TM_HIGH_STS, + tm_status, 2); + if (ret) + return ret; + + ret = adc5_gen3_status_clear(adc_tm5->dev_data, sdam_index, ADC5_GEN3_TM_HIGH_STS_CLR, + tm_status, 2); + if (ret) + return ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_CH_DATA0(0), + buf, 16); + return ret; +} + +static irqreturn_t adctm5_gen3_isr_thread(int irq, void *dev_id) +{ + struct adc_tm5_gen3_chip *adc_tm5 = dev_id; + int sdam_index = -1; + u8 tm_status[2] = { }; + u8 buf[16] = { }; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + struct adc_tm5_gen3_channel_props *chan_prop = &adc_tm5->chan_props[i]; + int offset = chan_prop->tm_chan_index; + bool upper_set, lower_set; + int ret; + + scoped_guard(adc5_gen3, adc_tm5) { + if (chan_prop->sdam_index != sdam_index) { + sdam_index = chan_prop->sdam_index; + ret = adc5_gen3_tm_status_check(adc_tm5, sdam_index, + tm_status, buf); + if (ret) + return IRQ_NONE; + } + + upper_set = ((tm_status[0] & BIT(offset)) && chan_prop->high_thr_en); + lower_set = ((tm_status[1] & BIT(offset)) && chan_prop->low_thr_en); + } + + if (!(upper_set || lower_set)) + continue; + + thermal_zone_device_update(chan_prop->tzd, THERMAL_TRIP_VIOLATED); + } + + return IRQ_HANDLED; +} + +static int adc_tm5_gen3_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct adc_tm5_gen3_channel_props *prop = thermal_zone_device_priv(tz); + struct adc_tm5_gen3_chip *adc_tm5; + + if (!prop || !prop->chip) + return -EINVAL; + + adc_tm5 = prop->chip; + + return adc5_gen3_get_scaled_reading(adc_tm5->dev, &prop->common_props, + temp); +} + +static int adc_tm5_gen3_disable_channel(struct adc_tm5_gen3_channel_props *prop) +{ + struct adc_tm5_gen3_chip *adc_tm5 = prop->chip; + int ret; + u8 val; + + prop->high_thr_en = false; + prop->low_thr_en = false; + + ret = adc5_gen3_poll_wait_hs(adc_tm5->dev_data, prop->sdam_index); + if (ret) + return ret; + + val = BIT(prop->tm_chan_index); + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TM_HIGH_STS_CLR, &val, sizeof(val)); + if (ret) + return ret; + + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TM_LOW_STS_CLR, &val, sizeof(val)); + if (ret) + return ret; + + val = MEAS_INT_DISABLE; + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TIMER_SEL, &val, sizeof(val)); + if (ret) + return ret; + + /* To indicate there is an actual conversion request */ + val = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index; + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_PERPH_CH, &val, sizeof(val)); + if (ret) + return ret; + + val = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_CONV_REQ, &val, sizeof(val)); +} + +static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, + int low_temp, int high_temp) +{ + struct adc_tm5_gen3_chip *adc_tm5 = prop->chip; + u8 buf[ADC_TM5_GEN3_CONFIG_REGS]; + u8 conv_req; + u16 adc_code; + int ret; + + ret = adc5_gen3_poll_wait_hs(adc_tm5->dev_data, prop->sdam_index); + if (ret < 0) + return ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_SID, buf, sizeof(buf)); + if (ret < 0) + return ret; + + /* Write SID */ + buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->common_props.sid); + + /* Select TM channel and indicate there is an actual conversion request */ + buf[1] = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index; + + buf[2] = prop->timer; + + /* Digital param selection */ + adc5_gen3_update_dig_param(&prop->common_props, &buf[3]); + + /* Update fast average sample value */ + buf[4] &= ~ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK; + buf[4] |= prop->common_props.avg_samples | ADC5_GEN3_FAST_AVG_CTL_EN; + + /* Select ADC channel */ + buf[5] = prop->common_props.channel; + + /* Select HW settle delay for channel */ + buf[6] = FIELD_PREP(ADC5_GEN3_HW_SETTLE_DELAY_MASK, + prop->common_props.hw_settle_time_us); + + /* High temperature corresponds to low voltage threshold */ + prop->low_thr_en = (high_temp != INT_MAX); + if (prop->low_thr_en) { + adc_code = qcom_adc_tm5_gen2_temp_res_scale(high_temp); + put_unaligned_le16(adc_code, &buf[8]); + } + + /* Low temperature corresponds to high voltage threshold */ + prop->high_thr_en = (low_temp != -INT_MAX); + if (prop->high_thr_en) { + adc_code = qcom_adc_tm5_gen2_temp_res_scale(low_temp); + put_unaligned_le16(adc_code, &buf[10]); + } + + buf[7] = 0; + if (prop->high_thr_en) + buf[7] |= ADC5_GEN3_HIGH_THR_INT_EN; + if (prop->low_thr_en) + buf[7] |= ADC5_GEN3_LOW_THR_INT_EN; + + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, ADC5_GEN3_SID, + buf, sizeof(buf)); + if (ret < 0) + return ret; + + conv_req = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_CONV_REQ, &conv_req, sizeof(conv_req)); +} + +static int adc_tm5_gen3_set_trip_temp(struct thermal_zone_device *tz, + int low_temp, int high_temp) +{ + struct adc_tm5_gen3_channel_props *prop = thermal_zone_device_priv(tz); + struct adc_tm5_gen3_chip *adc_tm5; + + if (!prop || !prop->chip) + return -EINVAL; + + adc_tm5 = prop->chip; + + dev_dbg(adc_tm5->dev, "channel:%s, low_temp(mdegC):%d, high_temp(mdegC):%d\n", + prop->common_props.label, low_temp, high_temp); + + guard(adc5_gen3)(adc_tm5); + + return adc_tm5_gen3_configure(prop, low_temp, high_temp); +} + +static const struct thermal_zone_device_ops adc_tm_ops = { + .get_temp = adc_tm5_gen3_get_temp, + .set_trips = adc_tm5_gen3_set_trip_temp, +}; + +static int adc_tm5_register_tzd(struct adc_tm5_gen3_chip *adc_tm5) +{ + struct thermal_zone_device *tzd; + unsigned int channel; + int ret; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + channel = ADC5_GEN3_V_CHAN(adc_tm5->chan_props[i].common_props); + tzd = devm_thermal_of_zone_register(adc_tm5->dev, channel, + &adc_tm5->chan_props[i], + &adc_tm_ops); + if (IS_ERR(tzd)) { + if (PTR_ERR(tzd) == -ENODEV) { + dev_info(adc_tm5->dev, + "thermal sensor on channel %d is not used\n", + channel); + continue; + } + return dev_err_probe(adc_tm5->dev, PTR_ERR(tzd), + "Error registering TZ zone:%ld for channel:%d\n", + PTR_ERR(tzd), channel); + } + adc_tm5->chan_props[i].tzd = tzd; + ret = devm_thermal_add_hwmon_sysfs(adc_tm5->dev, tzd); + if (ret) + return ret; + } + return 0; +} + +static void adc5_gen3_disable(void *data) +{ + struct adc_tm5_gen3_chip *adc_tm5 = data; + + guard(adc5_gen3)(adc_tm5); + /* Disable all available TM channels */ + for (int i = 0; i < adc_tm5->nchannels; i++) + adc_tm5_gen3_disable_channel(&adc_tm5->chan_props[i]); +} + +static int adc_tm5_probe(struct auxiliary_device *aux_dev, + const struct auxiliary_device_id *id) +{ + struct adc_tm5_gen3_chip *adc_tm5; + struct tm5_aux_dev_wrapper *aux_dev_wrapper; + struct device *dev = &aux_dev->dev; + int ret; + + adc_tm5 = devm_kzalloc(dev, sizeof(*adc_tm5), GFP_KERNEL); + if (!adc_tm5) + return -ENOMEM; + + aux_dev_wrapper = container_of(aux_dev, struct tm5_aux_dev_wrapper, + aux_dev); + + adc_tm5->dev = dev; + adc_tm5->dev_data = aux_dev_wrapper->dev_data; + adc_tm5->nchannels = aux_dev_wrapper->n_tm_channels; + adc_tm5->chan_props = devm_kcalloc(dev, aux_dev_wrapper->n_tm_channels, + sizeof(*adc_tm5->chan_props), GFP_KERNEL); + if (!adc_tm5->chan_props) + return -ENOMEM; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + adc_tm5->chan_props[i].common_props = aux_dev_wrapper->tm_props[i]; + adc_tm5->chan_props[i].timer = MEAS_INT_1S; + adc_tm5->chan_props[i].sdam_index = (i + 1) / 8; + adc_tm5->chan_props[i].tm_chan_index = (i + 1) % 8; + adc_tm5->chan_props[i].chip = adc_tm5; + } + + /* This is to disable all ADC_TM channels in case of probe failure. */ + ret = devm_add_action(dev, adc5_gen3_disable, adc_tm5); + if (ret) + return ret; + + /* + * First SDAM's interrupt is shared between main ADC driver + * and auxiliary TM driver, so its flags must include + * IRQF_SHARED. This is not needed for other SDAMs as they + * will be used only for TM functionality. + */ + + ret = devm_request_threaded_irq(dev, + adc_tm5->dev_data->base[0].irq, + adctm5_gen3_isr, adctm5_gen3_isr_thread, + IRQF_ONESHOT | IRQF_SHARED, + adc_tm5->dev_data->base[0].irq_name, + adc_tm5); + if (ret < 0) + return ret; + + for (int i = 1; i < adc_tm5->dev_data->num_sdams; i++) { + ret = devm_request_threaded_irq(dev, + adc_tm5->dev_data->base[i].irq, + adctm5_gen3_isr, adctm5_gen3_isr_thread, + IRQF_ONESHOT, adc_tm5->dev_data->base[i].irq_name, + adc_tm5); + if (ret < 0) + return ret; + } + + return adc_tm5_register_tzd(adc_tm5); +} + +static const struct auxiliary_device_id adctm5_auxiliary_id_table[] = { + { .name = "qcom_spmi_adc5_gen3.adc5_tm_gen3", }, + { } +}; + +MODULE_DEVICE_TABLE(auxiliary, adctm5_auxiliary_id_table); + +static struct auxiliary_driver adctm5gen3_auxiliary_driver = { + .id_table = adctm5_auxiliary_id_table, + .probe = adc_tm5_probe, +}; + +module_auxiliary_driver(adctm5gen3_auxiliary_driver); + +MODULE_DESCRIPTION("SPMI PMIC Thermal Monitor ADC driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("QCOM_SPMI_ADC5_GEN3"); From e3d050b8af3edee6e995c32d24fefa00c4309f52 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 30 Apr 2026 14:28:56 +0530 Subject: [PATCH 0150/1058] FROMLIST: arm64: dts: qcom: Add header file for ADC5 Gen3 channel macros Add macro definitions for virtual channels (combination of ADC channel number and PMIC SID number), to be used in devicetree by clients of ADC5 GEN3 device and in the "reg" property of ADC channels. Link: https://lore.kernel.org/all/20260430-adc5_gen3_dt-v1-1-ab2bb40fd490@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h | 88 +++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h diff --git a/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h b/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h new file mode 100644 index 0000000000000..aa8e54d7e786a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DTS_ARM64_QCOM_ADC5_GEN3_H__ +#define __DTS_ARM64_QCOM_ADC5_GEN3_H__ + +/* ADC channels for PMIC5 Gen3 */ + +#define VIRT_CHAN(sid, chan) ((sid) << 8 | (chan)) + +#define ADC5_GEN3_REF_GND(sid) VIRT_CHAN(sid, 0x00) +#define ADC5_GEN3_1P25VREF(sid) VIRT_CHAN(sid, 0x01) +#define ADC5_GEN3_VREF_VADC(sid) VIRT_CHAN(sid, 0x02) +#define ADC5_GEN3_DIE_TEMP(sid) VIRT_CHAN(sid, 0x03) + +#define ADC5_GEN3_AMUX1_THM(sid) VIRT_CHAN(sid, 0x04) +#define ADC5_GEN3_AMUX2_THM(sid) VIRT_CHAN(sid, 0x05) +#define ADC5_GEN3_AMUX3_THM(sid) VIRT_CHAN(sid, 0x06) +#define ADC5_GEN3_AMUX4_THM(sid) VIRT_CHAN(sid, 0x07) +#define ADC5_GEN3_AMUX5_THM(sid) VIRT_CHAN(sid, 0x08) +#define ADC5_GEN3_AMUX6_THM(sid) VIRT_CHAN(sid, 0x09) +#define ADC5_GEN3_AMUX1_GPIO(sid) VIRT_CHAN(sid, 0x0a) +#define ADC5_GEN3_AMUX2_GPIO(sid) VIRT_CHAN(sid, 0x0b) +#define ADC5_GEN3_AMUX3_GPIO(sid) VIRT_CHAN(sid, 0x0c) +#define ADC5_GEN3_AMUX4_GPIO(sid) VIRT_CHAN(sid, 0x0d) + +#define ADC5_GEN3_CHG_TEMP(sid) VIRT_CHAN(sid, 0x10) +#define ADC5_GEN3_USB_SNS_V_16(sid) VIRT_CHAN(sid, 0x11) +#define ADC5_GEN3_VIN_DIV16_MUX(sid) VIRT_CHAN(sid, 0x12) +#define ADC5_GEN3_VREF_BAT_THERM(sid) VIRT_CHAN(sid, 0x15) +#define ADC5_GEN3_IIN_FB(sid) VIRT_CHAN(sid, 0x17) +#define ADC5_GEN3_TEMP_ALARM_LITE(sid) VIRT_CHAN(sid, 0x18) +#define ADC5_GEN3_IIN_SMB(sid) VIRT_CHAN(sid, 0x19) +#define ADC5_GEN3_ICHG_SMB(sid) VIRT_CHAN(sid, 0x1b) +#define ADC5_GEN3_ICHG_FB(sid) VIRT_CHAN(sid, 0xa1) + +/* 30k pull-up */ +#define ADC5_GEN3_AMUX1_THM_30K_PU(sid) VIRT_CHAN(sid, 0x24) +#define ADC5_GEN3_AMUX2_THM_30K_PU(sid) VIRT_CHAN(sid, 0x25) +#define ADC5_GEN3_AMUX3_THM_30K_PU(sid) VIRT_CHAN(sid, 0x26) +#define ADC5_GEN3_AMUX4_THM_30K_PU(sid) VIRT_CHAN(sid, 0x27) +#define ADC5_GEN3_AMUX5_THM_30K_PU(sid) VIRT_CHAN(sid, 0x28) +#define ADC5_GEN3_AMUX6_THM_30K_PU(sid) VIRT_CHAN(sid, 0x29) +#define ADC5_GEN3_AMUX1_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2a) +#define ADC5_GEN3_AMUX2_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2b) +#define ADC5_GEN3_AMUX3_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2c) +#define ADC5_GEN3_AMUX4_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2d) + +/* 100k pull-up */ +#define ADC5_GEN3_AMUX1_THM_100K_PU(sid) VIRT_CHAN(sid, 0x44) +#define ADC5_GEN3_AMUX2_THM_100K_PU(sid) VIRT_CHAN(sid, 0x45) +#define ADC5_GEN3_AMUX3_THM_100K_PU(sid) VIRT_CHAN(sid, 0x46) +#define ADC5_GEN3_AMUX4_THM_100K_PU(sid) VIRT_CHAN(sid, 0x47) +#define ADC5_GEN3_AMUX5_THM_100K_PU(sid) VIRT_CHAN(sid, 0x48) +#define ADC5_GEN3_AMUX6_THM_100K_PU(sid) VIRT_CHAN(sid, 0x49) +#define ADC5_GEN3_AMUX1_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4a) +#define ADC5_GEN3_AMUX2_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4b) +#define ADC5_GEN3_AMUX3_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4c) +#define ADC5_GEN3_AMUX4_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4d) + +/* 400k pull-up */ +#define ADC5_GEN3_AMUX1_THM_400K_PU(sid) VIRT_CHAN(sid, 0x64) +#define ADC5_GEN3_AMUX2_THM_400K_PU(sid) VIRT_CHAN(sid, 0x65) +#define ADC5_GEN3_AMUX3_THM_400K_PU(sid) VIRT_CHAN(sid, 0x66) +#define ADC5_GEN3_AMUX4_THM_400K_PU(sid) VIRT_CHAN(sid, 0x67) +#define ADC5_GEN3_AMUX5_THM_400K_PU(sid) VIRT_CHAN(sid, 0x68) +#define ADC5_GEN3_AMUX6_THM_400K_PU(sid) VIRT_CHAN(sid, 0x69) +#define ADC5_GEN3_AMUX1_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6a) +#define ADC5_GEN3_AMUX2_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6b) +#define ADC5_GEN3_AMUX3_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6c) +#define ADC5_GEN3_AMUX4_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6d) + +/* 1/3 Divider */ +#define ADC5_GEN3_AMUX1_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8a) +#define ADC5_GEN3_AMUX2_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8b) +#define ADC5_GEN3_AMUX3_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8c) +#define ADC5_GEN3_AMUX4_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8d) + +#define ADC5_GEN3_VPH_PWR(sid) VIRT_CHAN(sid, 0x8e) +#define ADC5_GEN3_VBAT_SNS_QBG(sid) VIRT_CHAN(sid, 0x8f) + +#define ADC5_GEN3_VBAT_SNS_CHGR(sid) VIRT_CHAN(sid, 0x94) +#define ADC5_GEN3_VBAT_2S_MID_QBG(sid) VIRT_CHAN(sid, 0x96) +#define ADC5_GEN3_VBAT_2S_MID_CHGR(sid) VIRT_CHAN(sid, 0x9d) + +#endif /* __DTS_ARM64_QCOM_ADC5_GEN3_H__ */ From 6ff7ac7a98e82b66064f201fcab092a8ac11e7f2 Mon Sep 17 00:00:00 2001 From: Ayyagari Ushasreevalli Date: Thu, 30 Apr 2026 14:28:57 +0530 Subject: [PATCH 0151/1058] FROMLIST: arm64: dts: qcom: lemans-pmics: Add ADC support for PMM8654au Add ADC nodes for the four PMM8654au PMICs (pmm8654au_0 through pmm8654au_3) on the Lemans platform. Each ADC node exposes the following ADC channels: - DIE_TEMP: PMIC die temperature channel - VPH_PWR: Battery/supply voltage channel Also add the io-channels and io-channel-names properties under the temp-alarm nodes so that they can get temperature reading from the ADC die_temp channels. Link: https://lore.kernel.org/all/20260430-adc5_gen3_dt-v1-2-ab2bb40fd490@oss.qualcomm.com/ Signed-off-by: Ayyagari Ushasreevalli Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/lemans-pmics.dtsi | 93 ++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi index 341119fc82440..6caec3e4df4bb 100644 --- a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi @@ -5,6 +5,7 @@ #include #include +#include "qcom-adc5-gen3.h" / { thermal-zones { @@ -110,6 +111,8 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x0 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_0_adc ADC5_GEN3_DIE_TEMP(0)>; + io-channel-names = "thermal"; }; pmm8654au_0_pon: pon@1200 { @@ -141,6 +144,27 @@ interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; }; + pmm8654au_0_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@3 { + reg = ; + label = "pmm8654au_0_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@8e { + reg = ; + label = "pmm8654au_0_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8654au_0_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -176,6 +200,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_1_adc ADC5_GEN3_DIE_TEMP(2)>; + io-channel-names = "thermal"; + }; + + pmm8654au_1_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x2 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@203 { + reg = ; + label = "pmm8654au_1_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@28e { + reg = ; + label = "pmm8654au_1_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_1_gpios: gpio@8800 { @@ -200,6 +247,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x4 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_2_adc ADC5_GEN3_DIE_TEMP(4)>; + io-channel-names = "thermal"; + }; + + pmm8654au_2_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x4 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@403 { + reg = ; + label = "pmm8654au_2_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@48e { + reg = ; + label = "pmm8654au_2_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_2_gpios: gpio@8800 { @@ -224,6 +294,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x6 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_3_adc ADC5_GEN3_DIE_TEMP(6)>; + io-channel-names = "thermal"; + }; + + pmm8654au_3_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x6 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@603 { + reg = ; + label = "pmm8654au_3_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@68e { + reg = ; + label = "pmm8654au_3_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_3_gpios: gpio@8800 { From 86a1828edec07f98a80d498477dda4101c3e0bee Mon Sep 17 00:00:00 2001 From: Ayyagari Ushasreevalli Date: Thu, 30 Apr 2026 14:28:58 +0530 Subject: [PATCH 0152/1058] FROMLIST: arm64: dts: qcom: monaco-pmics: Add ADC support for PMM8620AU Add ADC nodes for PMM8620AU PMIC instances (SID 0 and SID 2) present on the Monaco platform. Each ADC node exposes the following ADC channels: - DIE_TEMP: PMIC die temperature channel - VPH_PWR: Battery/supply voltage channel Link: https://lore.kernel.org/all/20260430-adc5_gen3_dt-v1-3-ab2bb40fd490@oss.qualcomm.com/ Signed-off-by: Ayyagari Ushasreevalli Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/monaco-pmics.dtsi | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi index e990d7367719b..232bcb942b54c 100644 --- a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi @@ -5,6 +5,7 @@ #include #include +#include "qcom-adc5-gen3.h" &spmi_bus { pmm8620au_0: pmic@0 { @@ -20,6 +21,27 @@ interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; }; + pmm8620au_0_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@3 { + reg = ; + label = "pmm8620au_0_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@8e { + reg = ; + label = "pmm8620au_0_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8620au_0_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -37,6 +59,27 @@ #address-cells = <1>; #size-cells = <0>; + pmm8650au_1_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x2 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@203 { + reg = ; + label = "pmm8650au_1_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@28e { + reg = ; + label = "pmm8650au_1_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8650au_1_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; From 37c66db9917203d966b2853c8f63f46b2b9edcf4 Mon Sep 17 00:00:00 2001 From: Satya Priya Kakitapalli Date: Mon, 1 Jun 2026 16:31:18 +0530 Subject: [PATCH 0153/1058] FROMLIST: dt-bindings: thermal: Add Qualcomm MBG thermal monitor support Add bindings for the Qualcomm MBG (Master Bandgap) temperature alarm peripheral found on the PM8775 PMIC. Unlike the existing SPMI temp alarm peripheral, the MBG peripheral supports both hot and cold thresholdi monitoring across two programmable levels (LVL1 and LVL2), with interrupt status reported via a fault status register over SPMI. Link: https://lore.kernel.org/all/20260601-spmi-mbg-driver-v1-1-b4892b55a17f@oss.qualcomm.com/ Signed-off-by: Satya Priya Kakitapalli Co-developed-by: Sachin Gupta Signed-off-by: Sachin Gupta --- .../bindings/mfd/qcom,spmi-pmic.yaml | 4 ++ .../bindings/thermal/qcom-spmi-mbg-tm.yaml | 72 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 644c42b5e2e57..5f409fe700b22 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -193,6 +193,10 @@ patternProperties: type: object $ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml# + "^temperature-sensor@[0-9a-f]+$": + type: object + $ref: /schemas/thermal/qcom-spmi-mbg-tm.yaml# + "^typec@[0-9a-f]+$": type: object $ref: /schemas/usb/qcom,pmic-typec.yaml# diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml b/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml new file mode 100644 index 0000000000000..a0ecc9f35cf6e --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/qcom-spmi-mbg-tm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm's SPMI PMIC MBG Thermal Monitoring + +maintainers: + - Jishnu Prakash + - Kamal Wadhwa + +description: + Qualcomm's MBG(Master Bandgap) temperature alarm monitors the die + temperature and generates an interrupt if the PMIC die temperature is + over a set of programmable temperature thresholds. It allows monitoring + for both hot and cold, LVL1 and LVL2 thresholds, which makes it different + from the existing temp alarm peripheral. The interrupt comes over SPMI + and the MBG's fault status register gives details to understand whether + it is a hot/cold and LVL1/LVL2 violation. + +properties: + compatible: + const: qcom,pm8775-mbg-tm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + io-channels: + items: + - description: ADC channel, which reports chip die temperature. + + io-channel-names: + items: + - const: thermal + + '#thermal-sensor-cells': + const: 0 + +required: + - compatible + - reg + - interrupts + - io-channels + - io-channel-names + +allOf: + - $ref: thermal-sensor.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + temperature-sensor@d700 { + compatible = "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts = <0x1 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pm8775_adc 0x3>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + }; +... From 6f59fadaf0f63b094a3084ddd19b01056bfb7d03 Mon Sep 17 00:00:00 2001 From: Satya Priya Kakitapalli Date: Mon, 1 Jun 2026 16:31:19 +0530 Subject: [PATCH 0154/1058] FROMLIST: thermal: qcom: Add support for Qualcomm MBG thermal monitoring Add driver for the Qualcomm MBG thermal monitoring device. It monitors the die temperature, and when there is a level 1 upper threshold violation, it receives an interrupt over spmi. The driver reads the fault status register and notifies thermal accordingly. Link: https://lore.kernel.org/all/20260601-spmi-mbg-driver-v1-2-b4892b55a17f@oss.qualcomm.com/ Signed-off-by: Satya Priya Kakitapalli Co-developed-by: Sachin Gupta Signed-off-by: Sachin Gupta --- drivers/thermal/qcom/Kconfig | 11 + drivers/thermal/qcom/Makefile | 1 + drivers/thermal/qcom/qcom-spmi-mbg-tm.c | 254 ++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 drivers/thermal/qcom/qcom-spmi-mbg-tm.c diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig index 1acb11e4ac800..2d6df24e676ba 100644 --- a/drivers/thermal/qcom/Kconfig +++ b/drivers/thermal/qcom/Kconfig @@ -30,6 +30,17 @@ config QCOM_SPMI_ADC_TM5_GEN3 Thermal client sets threshold temperature for both warm and cool and gets updated when a threshold is reached. +config QCOM_SPMI_MBG_TM + tristate "Qualcomm SPMI PMIC MBG Temperature monitor" + depends on QCOM_SPMI_ADC5_GEN3 + select REGMAP_SPMI + help + This enables a thermal driver for the MBG thermal monitoring device. + It shows up in sysfs as a thermal sensor with single trip point. + It notifies the thermal framework when this trip is violated. The + temperature reported by the thermal sensor reflects the real + time die temperature through ADC channel. + config QCOM_SPMI_TEMP_ALARM tristate "Qualcomm SPMI PMIC Temperature Alarm" depends on OF && SPMI && IIO diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 828d9e7bc7970..937ba0fe28013 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -5,5 +5,6 @@ qcom_tsens-y += tsens.o tsens-v2.o tsens-v1.o tsens-v0_1.o \ tsens-8960.o obj-$(CONFIG_QCOM_SPMI_ADC_TM5) += qcom-spmi-adc-tm5.o obj-$(CONFIG_QCOM_SPMI_ADC_TM5_GEN3) += qcom-spmi-adc-tm5-gen3.o +obj-$(CONFIG_QCOM_SPMI_MBG_TM) += qcom-spmi-mbg-tm.o obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o obj-$(CONFIG_QCOM_LMH) += lmh.o diff --git a/drivers/thermal/qcom/qcom-spmi-mbg-tm.c b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c new file mode 100644 index 0000000000000..60190b341fc7c --- /dev/null +++ b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBG_TEMP_MON2_FAULT_STATUS 0x50 + +#define MON_FAULT_STATUS_MASK GENMASK(7, 4) +#define MON_FAULT_LVL1_UPR 0x5 + +#define MON2_LVL1_UP_THRESH 0x59 + +#define MBG_TEMP_MON2_MISC_CFG 0x5f +#define MON2_UP_THRESH_EN BIT(1) + +#define MBG_TEMP_STEP_MV 8 +#define MBG_TEMP_DEFAULT_TEMP_MV 600 +#define MBG_TEMP_CONSTANT 1000 +#define MBG_MIN_TRIP_TEMP 25000 +#define MBG_MAX_SUPPORTED_TEMP 160000 + +/** + * struct mbg_tm_chip - MBG thermal monitor device data. + * @map: regmap for accessing MBG thermal registers. + * @dev: mbg_tm_chip device. + * @tz_dev: thermal zone device registered with the thermal framework. + * @lock: mbg_tm_chip lock for set trip temperature. + * @base: base register offset for this MBG instance + * @irq: interrupt line used to signal threshold events + * @last_temp: last measured temperature. + * @last_thres_crossed: indicates whether the last interrupt crossed a threshold + * @adc: IIO ADC channel used for temperature sensing + */ +struct mbg_tm_chip { + struct regmap *map; + struct device *dev; + struct thermal_zone_device *tz_dev; + struct mutex lock; + unsigned int base; + int irq; + int last_temp; + bool last_thres_crossed; + struct iio_channel *adc; +}; + +/** + * struct mbg_map_table - temperature to voltage mapping entry + * @min_temp: minimum temperature supported by this mapping entry + * @vtemp0: reference voltage or ADC code corresponding to the temperature + * @tc: temperature coefficient used for conversion calculations + */ +struct mbg_map_table { + int min_temp; + int vtemp0; + int tc; +}; + +static const struct mbg_map_table map_table[] = { + /* minT vtemp0 tc */ + { -60000, 4337, 1967 }, + { -40000, 4731, 1964 }, + { -20000, 5124, 1957 }, + { 0, 5515, 1949 }, + { 20000, 5905, 1940 }, + { 40000, 6293, 1930 }, + { 60000, 6679, 1921 }, + { 80000, 7064, 1910 }, + { 100000, 7446, 1896 }, + { 120000, 7825, 1878 }, + { 140000, 8201, 1859 }, +}; + +static int mbg_tm_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz); + int ret, milli_celsius; + + if (chip->last_thres_crossed) { + dev_dbg(chip->dev, "last_temp: %d\n", chip->last_temp); + chip->last_thres_crossed = false; + *temp = chip->last_temp; + return 0; + } + + ret = iio_read_channel_processed(chip->adc, &milli_celsius); + if (ret < 0) { + dev_err(chip->dev, "Failed to read iio channel with %d\n", ret); + return ret; + } + + *temp = milli_celsius; + + return 0; +} + +static int temp_to_vtemp_mv(int temp) +{ + int idx, vtemp, tc = 0, t0 = 0, vtemp0 = 0; + + for (idx = 0; idx < ARRAY_SIZE(map_table); idx++) + if (temp >= map_table[idx].min_temp && + temp < (map_table[idx].min_temp + 20000)) { + tc = map_table[idx].tc; + t0 = map_table[idx].min_temp; + vtemp0 = map_table[idx].vtemp0; + break; + } + + /* + * Formula to calculate vtemp(mV) from a given temp + * vtemp = (temp - minT) * tc + vtemp0 + * tc, t0 and vtemp0 values are mentioned in the map_table array. + */ + vtemp = ((temp - t0) * tc + vtemp0 * 100000) / 1000000; + + /* step size is 8mV */ + return abs(vtemp - MBG_TEMP_DEFAULT_TEMP_MV) / MBG_TEMP_STEP_MV; +} + +static int mbg_tm_set_trip_temp(struct thermal_zone_device *tz, int low_temp, + int temp) +{ + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz); + int ret = 0; + + guard(mutex)(&chip->lock); + + /* The HW has a limitation that the trip set must be above 25C */ + if (temp > MBG_MIN_TRIP_TEMP && temp < MBG_MAX_SUPPORTED_TEMP) { + ret = regmap_set_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG, + MON2_UP_THRESH_EN); + if (ret < 0) + return ret; + + ret = regmap_write(chip->map, chip->base + MON2_LVL1_UP_THRESH, + temp_to_vtemp_mv(temp)); + if (ret < 0) + return ret; + } else { + dev_dbg(chip->dev, "Set trip b/w 25C and 160C\n"); + ret = regmap_clear_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG, + MON2_UP_THRESH_EN); + return ret; + } + + /* + * Configure the last_temp one degree higher, to ensure the + * violated temp is returned to thermal framework when it reads + * temperature for the first time after the violation happens. + * This is needed to account for the inaccuracy in the conversion + * formula used which leads to the thermal framework setting back + * the same thresholds in case the temperature it reads does not + * show violation. + */ + chip->last_temp = temp + MBG_TEMP_CONSTANT; + + return ret; +} + +static const struct thermal_zone_device_ops mbg_tm_ops = { + .get_temp = mbg_tm_get_temp, + .set_trips = mbg_tm_set_trip_temp, +}; + +static irqreturn_t mbg_tm_isr(int irq, void *data) +{ + struct mbg_tm_chip *chip = data; + int ret, val; + + scoped_guard(mutex, &chip->lock) { + ret = regmap_read(chip->map, chip->base + MBG_TEMP_MON2_FAULT_STATUS, &val); + if (ret < 0) + return IRQ_HANDLED; + } + + if (FIELD_GET(MON_FAULT_STATUS_MASK, val) & MON_FAULT_LVL1_UPR) { + chip->last_thres_crossed = true; + dev_dbg(chip->dev, "Notifying Thermal, fault status=%d\n", val); + thermal_zone_device_update(chip->tz_dev, THERMAL_TRIP_VIOLATED); + } else { + dev_dbg(chip->dev, "Lvl1 upper threshold not violated, ignoring interrupt\n"); + } + + return IRQ_HANDLED; +} + +static int mbg_tm_probe(struct platform_device *pdev) +{ + struct mbg_tm_chip *chip; + struct device_node *node = pdev->dev.of_node; + u32 res; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &pdev->dev; + + mutex_init(&chip->lock); + + chip->map = dev_get_regmap(pdev->dev.parent, NULL); + if (!chip->map) + return -ENXIO; + + ret = device_property_read_u32(chip->dev, "reg", &res); + if (ret < 0) + return dev_err_probe(chip->dev, ret, "Couldn't read reg property\n"); + + chip->base = res; + + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) + return dev_err_probe(chip->dev, chip->irq, "Failed to get irq\n"); + + chip->adc = devm_iio_channel_get(&pdev->dev, "thermal"); + if (IS_ERR(chip->adc)) + return dev_err_probe(chip->dev, PTR_ERR(chip->adc), "Failed to get adc channel\n"); + + chip->tz_dev = devm_thermal_of_zone_register(chip->dev, 0, chip, &mbg_tm_ops); + if (IS_ERR(chip->tz_dev)) + return dev_err_probe(chip->dev, PTR_ERR(chip->tz_dev), + "Failed to register sensor\n"); + + return devm_request_threaded_irq(&pdev->dev, chip->irq, NULL, mbg_tm_isr, IRQF_ONESHOT, + node->name, chip); +} + +static const struct of_device_id mbg_tm_match_table[] = { + { .compatible = "qcom,pm8775-mbg-tm" }, + { } +}; +MODULE_DEVICE_TABLE(of, mbg_tm_match_table); + +static struct platform_driver mbg_tm_driver = { + .driver = { + .name = "qcom-spmi-mbg-tm", + .of_match_table = mbg_tm_match_table, + }, + .probe = mbg_tm_probe, +}; +module_platform_driver(mbg_tm_driver); + +MODULE_DESCRIPTION("PMIC MBG Temperature monitor driver"); +MODULE_LICENSE("GPL"); From 6fb618c321fd27ccf873f5b4bc6737baee8fd8bb Mon Sep 17 00:00:00 2001 From: Ayyagari Ushasreevalli Date: Sun, 14 Jun 2026 13:35:11 +0530 Subject: [PATCH 0155/1058] FROMLIST: arm64: dts: qcom: hamoa-pmics: Add ADC support Add ADC node and define channels for: - Die temperature for PMK8550, PM8550VE* and PMC8380* PMICs. - PM8550: Die temperature, VPH power, and system thermistors. Define thermal zones 'sys-0-thermal' through 'sys-6-thermal' which correspond to the off-PMIC system thermistors connected via PM8550 AMUX/GPIO lines. Also,add io-channels and io-channel-names properties to the temp_alarm nodes so that they can get temperature reading from the ADC die_temp channels. Link: https://lore.kernel.org/all/20260614-adc5_gen3_dt-v2-4-32ec576c5865@oss.qualcomm.com/ Signed-off-by: Ayyagari Ushasreevalli Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi | 250 ++++++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi index 6a31a0adf8be4..2e746ede850f8 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include "qcom-adc5-gen3.h" / { thermal-zones { @@ -189,6 +191,90 @@ }; }; }; + + sys-0-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX1_GPIO_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX2_GPIO_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX1_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX2_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-4-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX3_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-5-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX4_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-6-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX5_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; }; }; @@ -277,6 +363,142 @@ status = "disabled"; }; + + pmk8550_vadc: adc@9000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x9000>, <0x9100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x90 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x91 0x1 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #io-channel-cells = <1>; + pinctrl-0 = <&sys_therm_0_gpio3>, <&sys_therm_1_gpio4>; + pinctrl-names = "default"; + + channel@3 { + reg = ; + label = "pmk8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@103 { + reg = ; + label = "pm8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@18e { + reg = ; + label = "pm8550_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + + channel@14a { + reg = ; + label = "pm8550_gpio_01"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@14b { + reg = ; + label = "pm8550_gpio_02"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@144 { + reg = ; + label = "pm8550_therm_2"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@145 { + reg = ; + label = "pm8550_therm_3"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@146 { + reg = ; + label = "pm8550_therm_4"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@147 { + reg = ; + label = "pm8550_therm_5"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@148 { + reg = ; + label = "pm8550_therm_6"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@203 { + reg = ; + label = "pm8550ve_2_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@303 { + reg = ; + label = "pmc8380_3_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@403 { + reg = ; + label = "pmc8380_4_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@503 { + reg = ; + label = "pmc8380_5_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@603 { + reg = ; + label = "pmc8380_6_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@803 { + reg = ; + label = "pm8550ve_8_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@903 { + reg = ; + label = "pm8550ve_9_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; }; /* PMC8380C */ @@ -291,6 +513,8 @@ reg = <0xa00>; interrupts = <0x1 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(1)>; + io-channel-names = "thermal"; }; pm8550_gpios: gpio@8800 { @@ -301,6 +525,18 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + + sys_therm_0_gpio3: sys-therm_0-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + sys_therm_1_gpio4: sys-therm-1-gpio4-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; }; pm8550_flash: led-controller@ee00 { @@ -329,6 +565,8 @@ reg = <0xa00>; interrupts = <0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(2)>; + io-channel-names = "thermal"; }; pm8550ve_2_gpios: gpio@8800 { @@ -354,6 +592,8 @@ reg = <0xa00>; interrupts = <0x3 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(3)>; + io-channel-names = "thermal"; }; pmc8380_3_gpios: gpio@8800 { @@ -378,6 +618,8 @@ reg = <0xa00>; interrupts = <0x4 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(4)>; + io-channel-names = "thermal"; }; pmc8380_4_gpios: gpio@8800 { @@ -402,6 +644,8 @@ reg = <0xa00>; interrupts = <0x5 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(5)>; + io-channel-names = "thermal"; }; pmc8380_5_gpios: gpio@8800 { @@ -426,6 +670,8 @@ reg = <0xa00>; interrupts = <0x6 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(6)>; + io-channel-names = "thermal"; }; pmc8380_6_gpios: gpio@8800 { @@ -451,6 +697,8 @@ reg = <0xa00>; interrupts = <0x8 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(8)>; + io-channel-names = "thermal"; }; pm8550ve_8_gpios: gpio@8800 { @@ -476,6 +724,8 @@ reg = <0xa00>; interrupts = <0x9 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(9)>; + io-channel-names = "thermal"; }; pm8550ve_9_gpios: gpio@8800 { From 41d79e21547080811f50913f30bf5a78738f080c Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Wed, 29 Apr 2026 22:31:40 +0530 Subject: [PATCH 0156/1058] FROMLIST: arm64: dts: qcom: qcs615-ride: Enable QSPI and NOR flash The QCS615 Ride board has a SPI-NOR flash connected to the QSPI controller on CS0. Enable the QSPI controller and add the corresponding SPI-NOR flash node to allow the system to access it. Link: https://lore.kernel.org/all/20260429-spi-nor-v5-5-993016c9711e@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 4ecc2c2dbbe92..ce61ff0d22299 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -517,6 +517,18 @@ }; }; +&qspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + }; +}; + &qupv3_id_0 { status = "okay"; }; From 2b861a28bbc80ff95be55bfeee96c2fbf623a9ba Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 22 May 2026 16:20:20 +0530 Subject: [PATCH 0157/1058] FROMLIST: arm64: dts: qcom: qcs615-ride: fix sdhc_2 vqmmc-supply for UHS-I mode SD card is detected as SDHS instead of UHS-I because sdhc_2 was configured with vreg_s4a as vqmmc-supply, which cannot switch between 1.8V and 3.3V. Switch vqmmc-supply to vreg_l2a and update its voltage range to 1800000-2960000 uV to enable proper UHS-I signaling. Link: https://lore.kernel.org/all/20260522105020.3588377-1-mchunara@oss.qualcomm.com/ Signed-off-by: Monish Chunara Signed-off-by: Pradeep P V K --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index ce61ff0d22299..6bd07c323a439 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -232,8 +232,8 @@ vreg_l2a: ldo2 { regulator-name = "vreg_l2a"; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <3100000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; regulator-initial-mode = ; regulator-allow-set-load; regulator-allowed-modes = ; vmmc-supply = <&vreg_l10a>; - vqmmc-supply = <&vreg_s4a>; + vqmmc-supply = <&vreg_l2a>; status = "okay"; }; From c918412b796fed89fc49fcd544d57932a90bfd68 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:20 +0530 Subject: [PATCH 0158/1058] FROMLIST: arm64: dts: qcom: talos: Add GEM_NOC interconnect for adreno SMMU On Talos platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-6-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/talos.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 312c7bece5f12..52df1b923bcf2 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -2090,6 +2090,8 @@ "iface"; power-domains = <&gpucc CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; stm@6002000 { From 998939a2c3de08871d99ef509ae4242bb19f6dbd Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 19:36:00 +0800 Subject: [PATCH 0159/1058] FROMLIST: arm64: dts: qcom: talos: Add label properties to CoreSight devices Add label properties to CTI and TPDM nodes in the talos device tree to provide human-readable identifiers for each CoreSight device. These labels allow userspace tools and the CoreSight framework to identify devices by name rather than by base address. Link: https://lore.kernel.org/linux-arm-msm/20260414-add-label-to-coresight-device-v2-2-5017d07358f2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/talos.dtsi | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 52df1b923bcf2..669d5df57aff8 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -2244,6 +2244,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss"; }; cti@6011000 { @@ -2252,6 +2253,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_1"; }; cti@6012000 { @@ -2260,6 +2262,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_2"; }; cti@6013000 { @@ -2268,6 +2271,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_3"; }; cti@6014000 { @@ -2276,6 +2280,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_4"; }; cti@6015000 { @@ -2284,6 +2289,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_5"; }; cti@6016000 { @@ -2292,6 +2298,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_6"; }; cti@6017000 { @@ -2300,6 +2307,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_7"; }; cti@6018000 { @@ -2308,6 +2316,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_8"; }; cti@6019000 { @@ -2316,6 +2325,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_9"; }; cti@601a000 { @@ -2324,6 +2334,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_10"; }; cti@601b000 { @@ -2332,6 +2343,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_11"; }; cti@601c000 { @@ -2340,6 +2352,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_12"; }; cti@601d000 { @@ -2348,6 +2361,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_13"; }; cti@601e000 { @@ -2356,6 +2370,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_14"; }; cti@601f000 { @@ -2364,6 +2379,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_15"; }; funnel@6041000 { @@ -2596,6 +2612,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdsp6"; }; tpdm@6840000 { @@ -2604,6 +2621,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_vsense"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2624,6 +2642,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2643,6 +2662,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_pimem"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2664,6 +2684,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2707,6 +2728,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp"; }; tpdm@6870000 { @@ -2715,6 +2737,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2735,6 +2758,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_wcss"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2757,6 +2781,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_monaq"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2800,6 +2825,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_qm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2820,6 +2846,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2840,6 +2867,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl0"; }; cti@6a03000 { @@ -2848,6 +2876,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl0_1"; }; cti@6a10000 { @@ -2856,6 +2885,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl1"; }; cti@6a11000 { @@ -2864,6 +2894,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl1_1"; }; funnel@6a05000 { @@ -2934,6 +2965,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2954,6 +2986,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2974,6 +3007,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao"; }; cti@6b05000 { @@ -2982,6 +3016,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_1"; }; cti@6b06000 { @@ -2990,6 +3025,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_2"; }; cti@6b07000 { @@ -2998,6 +3034,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_3"; }; funnel@6b08000 { @@ -3104,6 +3141,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aop_m3"; }; tpdm@6b48000 { @@ -3112,6 +3150,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_west"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3131,6 +3170,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_titan"; /* Not all required clocks can be enabled from the OS */ status = "fail"; @@ -3142,6 +3182,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_venus"; status = "disabled"; }; @@ -3151,6 +3192,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_center"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3170,6 +3212,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_dlct"; }; cti@6c2a000 { @@ -3178,6 +3221,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_dlct_1"; }; cti@7020000 { @@ -3186,6 +3230,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_2"; }; etm@7040000 { @@ -3214,6 +3259,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_3"; }; etm@7140000 { @@ -3242,6 +3288,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_4"; }; etm@7240000 { @@ -3270,6 +3317,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_5"; }; etm@7340000 { @@ -3298,6 +3346,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_6"; }; etm@7440000 { @@ -3326,6 +3375,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_7"; }; etm@7540000 { @@ -3354,6 +3404,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_8"; }; etm@7640000 { @@ -3382,6 +3433,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_9"; }; etm@7740000 { @@ -3556,6 +3608,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_olc"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3599,6 +3652,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3642,6 +3696,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3661,6 +3716,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3728,6 +3784,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss"; }; cti@78f0000 { @@ -3736,6 +3793,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_1"; }; cti@7900000 { @@ -3744,6 +3802,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_2"; }; remoteproc_cdsp: remoteproc@8300000 { From 2df60acc0ea2f0a7ed15202965438e3201cede34 Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 16:02:01 +0530 Subject: [PATCH 0160/1058] PENDING: arm64: dts: qcom: talos: enable video codec on Talos Enable video codec on Talos in the EL2 configuration and describe the firmware IOMMU mapping using the iommu-map property. Signed-off-by: Renjiang Han --- arch/arm64/boot/dts/qcom/talos-el2.dtso | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/talos-el2.dtso b/arch/arm64/boot/dts/qcom/talos-el2.dtso index f6818c058d724..08b5c9a537fb6 100644 --- a/arch/arm64/boot/dts/qcom/talos-el2.dtso +++ b/arch/arm64/boot/dts/qcom/talos-el2.dtso @@ -5,6 +5,8 @@ * Talos specific modifications required to boot in EL2. */ +#include + /dts-v1/; /plugin/; @@ -21,5 +23,6 @@ }; &venus { - status = "disabled"; + iommu-map = ; + status = "okay"; }; From dc1eec8a1679c205efa034f8110d2e0ec981154e Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:52:56 +0530 Subject: [PATCH 0161/1058] dt-bindings: remoteproc: qcom,pas: add thermal mitigation properties Document Qualcomm PAS remoteproc thermal mitigation properties used for QMI-based throttling. Add: - #cooling-cells (2 or 3) - tmd-names (thermal mitigation device names) Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-1-291a2ff4c634@oss.qualcomm.com Signed-off-by: Gaurav Kohli --- .../bindings/remoteproc/qcom,pas-common.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 4607b459131b4..0d07a07507620 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -79,6 +79,20 @@ properties: channels and devices related to the ADSP. unevaluatedProperties: false + '#cooling-cells': + description: + Number of cooling cells; 2 for min/max cooling state and 3 when + selecting a thermal mitigation device index. + enum: [2, 3] + + tmd-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + Names of the thermal mitigation devices available in remote processor + subsystem. + minItems: 1 + maxItems: 5 + glink-edge: $ref: /schemas/remoteproc/qcom,glink-edge.yaml# description: From 6141250b6a49ffc876daf35bcb81856d37306d43 Mon Sep 17 00:00:00 2001 From: Casey Connolly Date: Tue, 9 Jun 2026 15:52:57 +0530 Subject: [PATCH 0162/1058] soc: qcom: Add support for QMI TMD cooling devices Add a Qualcomm QMI Thermal Mitigation Device (TMD) to support thermal cooling devices backed by remote subsystems. On several Qualcomm platforms, remote processors (for example modem and CDSP) expose thermal mitigation controls through the TMD QMI service. Client drivers need a way to discover that service, map DT thermal mitigation endpoints to cooling devices, and forward cooling state updates to the remote subsystem. Co-developed-by: Gaurav Kohli Signed-off-by: Gaurav Kohli Signed-off-by: Casey Connolly Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-2-291a2ff4c634@oss.qualcomm.com --- MAINTAINERS | 6 + drivers/soc/qcom/Kconfig | 10 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/qmi_tmd.c | 602 +++++++++++++++++++++++++++++++ include/linux/soc/qcom/qmi.h | 1 + include/linux/soc/qcom/qmi_tmd.h | 23 ++ 6 files changed, 643 insertions(+) create mode 100644 drivers/soc/qcom/qmi_tmd.c create mode 100644 include/linux/soc/qcom/qmi_tmd.h diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a99..829ffcb528f47 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22330,6 +22330,12 @@ F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst F: drivers/net/ethernet/qualcomm/ppe/ +QUALCOMM QMI (REMOTEPROC THERMAL MITIGATION) TMD +M: Gaurav Kohli +L: linux-arm-msm@vger.kernel.org +L: linux-pm@vger.kernel.org +F: drivers/soc/qcom/qmi_tmd.c + QUALCOMM QSEECOM DRIVER M: Maximilian Luz L: linux-arm-msm@vger.kernel.org diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 2caadbbcf8307..a292ce57fd4a4 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -128,6 +128,16 @@ config QCOM_QMI_HELPERS tristate depends on NET +config QCOM_QMI_TMD + bool "Qualcomm QMI TMD library" if COMPILE_TEST + depends on ARCH_QCOM + select QCOM_QMI_HELPERS + help + This enables the QMI-based Thermal Mitigation Device (TMD) library + for Qualcomm remote subsystems. The library manages TMD messaging and + handles QMI communication with remote processors (modem, CDSP) to + exchange mitigation state and apply thermal mitigation requests. + config QCOM_RAMP_CTRL tristate "Qualcomm Ramp Controller driver" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index b7f1d2a573674..4544e61c74e73 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o CFLAGS_pmic_pdcharger_ulog.o := -I$(src) +obj-$(CONFIG_QCOM_QMI_TMD) += qmi_tmd.o obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o diff --git a/drivers/soc/qcom/qmi_tmd.c b/drivers/soc/qcom/qmi_tmd.c new file mode 100644 index 0000000000000..e09131e8ef0f6 --- /dev/null +++ b/drivers/soc/qcom/qmi_tmd.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QMI Thermal Mitigation Device (TMD) library. + * This library provides cooling device support for remote subsystems + * (modem and CDSP) running the TMD service via QMI. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QMI_TMD_INSTANCE_MODEM 0x0 +#define QMI_TMD_INSTANCE_CDSP 0x43 +#define QMI_TMD_INSTANCE_CDSP1 0x44 + +#define QMI_TMD_SERVICE_VERS_V01 0x01 + +#define QMI_TMD_SET_LEVEL_REQ 0x0021 +#define QMI_TMD_GET_DEV_LIST_REQ 0x0020 + +#define QMI_TMD_DEV_ID_LEN_MAX 32 +#define QMI_TMD_DEV_LIST_MAX 32 +#define QMI_TMD_RESP_TIMEOUT msecs_to_jiffies(100) +#define TMD_GET_LEVEL_REQ_MAX_LEN 36 +#define TMD_SET_LEVEL_REQ_MAX_LEN 40 + +#define TMD_GET_DEV_LIST_REQ_MAX_LEN 0 +#define TMD_GET_DEV_LIST_RESP_MAX_LEN 1099 + +struct tmd_dev_id { + char mitigation_dev_id[QMI_TMD_DEV_ID_LEN_MAX + 1]; +}; + +static const struct qmi_elem_info tmd_dev_id_ei[] = { + { + .data_type = QMI_STRING, + .elem_len = QMI_TMD_DEV_ID_LEN_MAX + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_id, + mitigation_dev_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_dev_list { + struct tmd_dev_id mitigation_dev_id; + u8 max_mitigation_level; +}; + +static const struct qmi_elem_info tmd_dev_list_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct tmd_dev_id), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_list, + mitigation_dev_id), + .ei_array = tmd_dev_id_ei, + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_list, + max_mitigation_level), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_get_dev_list_req { + char placeholder; +}; + +static const struct qmi_elem_info tmd_get_dev_list_req_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_get_dev_list_resp { + struct qmi_response_type_v01 resp; + u8 mitigation_device_list_valid; + u32 mitigation_device_list_len; + struct tmd_dev_list + mitigation_device_list[QMI_TMD_DEV_LIST_MAX]; +}; + +static const struct qmi_elem_info tmd_get_dev_list_resp_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_get_dev_list_resp, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_TMD_DEV_LIST_MAX, + .elem_size = sizeof(struct tmd_dev_list), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list), + .ei_array = tmd_dev_list_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_set_level_req { + struct tmd_dev_id mitigation_dev_id; + u8 mitigation_level; +}; + +static const struct qmi_elem_info tmd_set_level_req_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct tmd_dev_id), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct tmd_set_level_req, + mitigation_dev_id), + .ei_array = tmd_dev_id_ei, + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_set_level_req, + mitigation_level), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_set_level_resp { + struct qmi_response_type_v01 resp; +}; + +static const struct qmi_elem_info tmd_set_level_resp_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_set_level_resp, resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +/** + * struct qmi_tmd - A TMD cooling device + * @name: The name of this tmd shared by the remote subsystem + * @cdev: Thermal cooling device handle + * @cur_state: The current mitigation state + * @max_state: The maximum state + * @qmi_tmd_cli: Parent QMI TMD client + */ +struct qmi_tmd { + const char *name; + struct thermal_cooling_device *cdev; + unsigned int cur_state; + unsigned int max_state; + struct qmi_tmd_client *qmi_tmd_cli; +}; + +/** + * struct qmi_tmd_client - QMI TMD client state + * @dev: Device associated with this instance + * @handle: QMI connection handle + * @mutex: Lock to synchronise QMI communication + * @connection_active: Whether or not we're connected to the QMI TMD service + * @svc_arrive_work: Work item for initialising when the TMD service starts + * @num_tmds: Number of tmds described in the device tree + * @tmds: An array of tmd structures + */ +struct qmi_tmd_client { + struct device *dev; + struct qmi_handle handle; + /* protects QMI transactions and connection_active */ + struct mutex mutex; + bool connection_active; + struct work_struct svc_arrive_work; + int num_tmds; + struct qmi_tmd tmds[] __counted_by(num_tmds); +}; + +/* Notify the remote subsystem of the requested cooling state */ +static int qmi_tmd_send_state_request(struct qmi_tmd *tmd, int state) +{ + struct tmd_set_level_resp resp = { 0 }; + struct tmd_set_level_req req = { 0 }; + struct qmi_tmd_client *qmi_tmd_cli = tmd->qmi_tmd_cli; + struct qmi_txn txn; + int ret = 0; + + guard(mutex)(&qmi_tmd_cli->mutex); + + if (!qmi_tmd_cli->connection_active) + return 0; + + strscpy(req.mitigation_dev_id.mitigation_dev_id, tmd->name, + QMI_TMD_DEV_ID_LEN_MAX + 1); + req.mitigation_level = state; + + ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn, + tmd_set_level_resp_ei, &resp); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn init failed for %s ret %d\n", + state, tmd->name, ret); + return ret; + } + + ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn, + QMI_TMD_SET_LEVEL_REQ, + TMD_SET_LEVEL_REQ_MAX_LEN, + tmd_set_level_req_ei, &req); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn send failed for %s ret %d\n", + state, tmd->name, ret); + qmi_txn_cancel(&txn); + return ret; + } + + ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn wait failed for %s ret %d\n", + state, tmd->name, ret); + return ret; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + dev_err(qmi_tmd_cli->dev, + "qmi set state %d failed for %s result %#x error %#x\n", + state, tmd->name, + resp.resp.result, resp.resp.error); + return -EREMOTEIO; + } + + dev_dbg(qmi_tmd_cli->dev, "Requested state %d/%d for %s\n", state, + tmd->max_state, tmd->name); + + return 0; +} + +static int qmi_tmd_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct qmi_tmd *tmd = cdev->devdata; + + *state = tmd->max_state; + + return 0; +} + +static int qmi_tmd_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct qmi_tmd *tmd = cdev->devdata; + + *state = tmd->cur_state; + + return 0; +} + +static int qmi_tmd_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + struct qmi_tmd *tmd = cdev->devdata; + int ret; + + if (state > tmd->max_state) + return -EINVAL; + + if (tmd->cur_state == state) + return 0; + + ret = qmi_tmd_send_state_request(tmd, state); + if (!ret) + tmd->cur_state = state; + + return ret; +} + +static const struct thermal_cooling_device_ops qmi_tmd_cooling_ops = { + .get_max_state = qmi_tmd_get_max_state, + .get_cur_state = qmi_tmd_get_cur_state, + .set_cur_state = qmi_tmd_set_cur_state, +}; + +static int qmi_tmd_register(struct qmi_tmd_client *qmi_tmd_cli, + const char *label, u8 max_state) +{ + struct device *dev = qmi_tmd_cli->dev; + struct qmi_tmd *tmd; + int index; + + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) { + tmd = &qmi_tmd_cli->tmds[index]; + + if (!strncasecmp(tmd->name, label, + QMI_TMD_DEV_ID_LEN_MAX + 1)) + goto found; + } + + dev_dbg(qmi_tmd_cli->dev, + "TMD '%s' available in firmware but not specified in DT\n", + label); + return 0; + +found: + tmd->max_state = max_state; + + /* + * If the cooling device already exists then the QMI service went away and + * came back. So just make sure the current cooling device state is + * reflected on the remote side and then return. + */ + if (tmd->cdev) + return qmi_tmd_send_state_request(tmd, tmd->cur_state); + + tmd->cdev = thermal_of_cooling_device_register(dev->of_node, index, + label, tmd, &qmi_tmd_cooling_ops); + if (IS_ERR(tmd->cdev)) + return PTR_ERR(tmd->cdev); + + return 0; +} + +static void qmi_tmd_unregister(struct qmi_tmd_client *qmi_tmd_cli) +{ + struct qmi_tmd *tmd; + int index; + + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) { + tmd = &qmi_tmd_cli->tmds[index]; + + if (!tmd->cdev) + continue; + + thermal_cooling_device_unregister(tmd->cdev); + tmd->cdev = NULL; + } +} + +static void qmi_tmd_svc_arrive(struct work_struct *work) +{ + struct qmi_tmd_client *qmi_tmd_cli = + container_of(work, struct qmi_tmd_client, svc_arrive_work); + + struct tmd_get_dev_list_req req = { 0 }; + struct tmd_get_dev_list_resp *resp __free(kfree) = NULL; + int ret, i; + struct qmi_txn txn; + + resp = kzalloc_obj(*resp, GFP_KERNEL); + if (!resp) { + ret = -ENOMEM; + goto out; + } + + scoped_guard(mutex, &qmi_tmd_cli->mutex) { + ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn, + tmd_get_dev_list_resp_ei, resp); + if (ret < 0) + goto out; + + ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn, + QMI_TMD_GET_DEV_LIST_REQ, + TMD_GET_DEV_LIST_REQ_MAX_LEN, + tmd_get_dev_list_req_ei, &req); + if (ret < 0) { + qmi_txn_cancel(&txn); + goto out; + } + + ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT); + if (ret < 0) + goto out; + + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + ret = -EPROTO; + goto out; + } + + qmi_tmd_cli->connection_active = true; + } + + for (i = 0; i < resp->mitigation_device_list_len; i++) { + struct tmd_dev_list *device = + &resp->mitigation_device_list[i]; + + ret = qmi_tmd_register(qmi_tmd_cli, + device->mitigation_dev_id.mitigation_dev_id, + device->max_mitigation_level); + if (ret) + break; + } + +out: + if (ret) + dev_err(qmi_tmd_cli->dev, "Failed to initialize TMD service: %d\n", ret); +} + +static void qmi_tmd_del_server(struct qmi_handle *qmi, struct qmi_service *service) +{ + struct qmi_tmd_client *qmi_tmd_cli = + container_of(qmi, struct qmi_tmd_client, handle); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) + qmi_tmd_cli->connection_active = false; +} + +static int qmi_tmd_new_server(struct qmi_handle *qmi, struct qmi_service *service) +{ + struct sockaddr_qrtr sq = { AF_QIPCRTR, service->node, service->port }; + struct qmi_tmd_client *qmi_tmd_cli; + int ret; + + qmi_tmd_cli = container_of(qmi, struct qmi_tmd_client, handle); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) { + ret = kernel_connect(qmi->sock, (struct sockaddr_unsized *)&sq, + sizeof(sq), 0); + } + + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "QMI connect failed for node %u port %u: %d\n", + service->node, service->port, ret); + return ret; + } + + queue_work(system_highpri_wq, &qmi_tmd_cli->svc_arrive_work); + + return 0; +} + +static const struct qmi_ops qmi_tmd_ops = { + .new_server = qmi_tmd_new_server, + .del_server = qmi_tmd_del_server, +}; + +static int qmi_tmd_get_instance_id(const char *remoteproc_name) +{ + if (!strcmp(remoteproc_name, "modem")) + return QMI_TMD_INSTANCE_MODEM; + + if (!strcmp(remoteproc_name, "cdsp")) + return QMI_TMD_INSTANCE_CDSP; + + if (!strcmp(remoteproc_name, "cdsp1")) + return QMI_TMD_INSTANCE_CDSP1; + + return -ENODEV; +} + +/** + * qmi_tmd_init() - Initialize QMI TMD instance + * @dev: Device pointer + * @remoteproc_name: Remoteproc name (for example modem, cdsp) + * @tmd_names: Array of TMD names + * @num_tmds: Number of TMD names + * + * Return: Pointer to qmi_tmd_client on success, ERR_PTR on failure + */ +struct qmi_tmd_client *qmi_tmd_init(struct device *dev, + const char *remoteproc_name, + const char * const *tmd_names, + int num_tmds) +{ + struct qmi_tmd_client *qmi_tmd_cli; + int ret, i, instance_id; + + if (!dev || !remoteproc_name || !tmd_names || num_tmds <= 0) + return ERR_PTR(-EINVAL); + + instance_id = qmi_tmd_get_instance_id(remoteproc_name); + if (instance_id < 0) { + dev_err(dev, "Unsupported remoteproc name '%s' for TMD lookup\n", + remoteproc_name); + return ERR_PTR(instance_id); + } + + qmi_tmd_cli = devm_kzalloc(dev, struct_size(qmi_tmd_cli, tmds, num_tmds), GFP_KERNEL); + if (!qmi_tmd_cli) + return ERR_PTR(-ENOMEM); + + qmi_tmd_cli->dev = dev; + qmi_tmd_cli->num_tmds = num_tmds; + mutex_init(&qmi_tmd_cli->mutex); + INIT_WORK(&qmi_tmd_cli->svc_arrive_work, qmi_tmd_svc_arrive); + + /* Initialize TMD structures */ + for (i = 0; i < num_tmds; i++) { + qmi_tmd_cli->tmds[i].name = tmd_names[i]; + qmi_tmd_cli->tmds[i].qmi_tmd_cli = qmi_tmd_cli; + } + + ret = qmi_handle_init(&qmi_tmd_cli->handle, + TMD_GET_DEV_LIST_RESP_MAX_LEN, + &qmi_tmd_ops, NULL); + if (ret < 0) { + dev_err(dev, "QMI handle init failed: %d\n", ret); + return ERR_PTR(ret); + } + + ret = qmi_add_lookup(&qmi_tmd_cli->handle, QMI_SERVICE_ID_TMD, + QMI_TMD_SERVICE_VERS_V01, instance_id); + if (ret < 0) { + dev_err(dev, "QMI add lookup failed: %d\n", ret); + goto err_release_handle; + } + + return qmi_tmd_cli; + +err_release_handle: + qmi_handle_release(&qmi_tmd_cli->handle); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(qmi_tmd_init); + +/** + * qmi_tmd_exit() - Deinitialize QMI TMD instance + * @qmi_tmd_cli: QMI TMD client to deinitialize + */ +void qmi_tmd_exit(struct qmi_tmd_client *qmi_tmd_cli) +{ + if (!qmi_tmd_cli) + return; + + cancel_work_sync(&qmi_tmd_cli->svc_arrive_work); + qmi_handle_release(&qmi_tmd_cli->handle); + qmi_tmd_unregister(qmi_tmd_cli); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) + qmi_tmd_cli->connection_active = false; +} +EXPORT_SYMBOL_GPL(qmi_tmd_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm QMI Thermal Mitigation library"); diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h index b9dcb437a0be5..683d27cee4132 100644 --- a/include/linux/soc/qcom/qmi.h +++ b/include/linux/soc/qcom/qmi.h @@ -96,6 +96,7 @@ struct qmi_elem_info { * Enumerate the IDs of the QMI services */ #define QMI_SERVICE_ID_TEST 0x0f /* 15 */ +#define QMI_SERVICE_ID_TMD 0x18 /* 24 */ #define QMI_SERVICE_ID_SSCTL 0x2b /* 43 */ #define QMI_SERVICE_ID_IPA 0x31 /* 49 */ #define QMI_SERVICE_ID_SERVREG_LOC 0x40 /* 64 */ diff --git a/include/linux/soc/qcom/qmi_tmd.h b/include/linux/soc/qcom/qmi_tmd.h new file mode 100644 index 0000000000000..75373eb09d618 --- /dev/null +++ b/include/linux/soc/qcom/qmi_tmd.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QMI Thermal Mitigation Device (TMD) library header. + */ + +#ifndef __QMI_TMD_H__ +#define __QMI_TMD_H__ + +struct device; +struct qmi_tmd_client; + +struct qmi_tmd_client *qmi_tmd_init(struct device *dev, + const char *remoteproc_name, + const char * const *tmd_names, + int num_tmds); + +void qmi_tmd_exit(struct qmi_tmd_client *tmd_cli); + +#endif /* __QMI_TMD_H__ */ + From 5de58f932f1ab3ddf66805fdcf9e7cd0ed51026d Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:52:58 +0530 Subject: [PATCH 0163/1058] remoteproc: qcom: pas: register TMD thermal cooling devices Add support for Thermal Mitigation Devices (TMDs) to enable thermal throttling of remote processors through QMI. This enables the thermal framework to request mitigation when remote subsystems (modem, CDSP) contribute to thermal issues. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-3-291a2ff4c634@oss.qualcomm.com Signed-off-by: Gaurav Kohli --- drivers/remoteproc/Kconfig | 1 + drivers/remoteproc/qcom_q6v5_pas.c | 61 +++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c521c744e7dbe..4fb2163c06556 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -228,6 +228,7 @@ config QCOM_Q6V5_PAS select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON + select QCOM_QMI_TMD select QCOM_RPROC_COMMON select QCOM_SCM help diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 808e9609988d3..25f17ed612017 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -5,6 +5,7 @@ * Copyright (C) 2016 Linaro Ltd * Copyright (C) 2014 Sony Mobile Communications AB * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -117,6 +119,8 @@ struct qcom_pas { struct qcom_scm_pas_context *pas_ctx; struct qcom_scm_pas_context *dtb_pas_ctx; + + struct qmi_tmd_client *tmd_inst; }; static void qcom_pas_segment_dump(struct rproc *rproc, @@ -730,6 +734,49 @@ static void qcom_pas_unassign_memory_region(struct qcom_pas *pas) } } +static int qcom_pas_setup_tmd(struct qcom_pas *pas) +{ + struct device *dev = pas->dev; + struct device_node *np = dev->of_node; + const char **tmd_names; + int num_tmds, ret, i; + + if (!of_find_property(np, "tmd-names", NULL)) + return 0; + + /* Get the TMD names array */ + num_tmds = of_property_count_strings(np, "tmd-names"); + if (num_tmds <= 0) + return 0; + + tmd_names = devm_kcalloc(dev, num_tmds, sizeof(*tmd_names), GFP_KERNEL); + if (!tmd_names) + return -ENOMEM; + + for (i = 0; i < num_tmds; i++) { + ret = of_property_read_string_index(np, "tmd-names", i, + &tmd_names[i]); + if (ret) { + dev_err(dev, "Failed to read tmd-names[%d]: %d\n", i, ret); + return ret; + } + } + + pas->tmd_inst = qmi_tmd_init(dev, pas->info_name, tmd_names, num_tmds); + if (IS_ERR(pas->tmd_inst)) { + dev_err(dev, "Failed to register '%s'\n", pas->info_name); + + ret = PTR_ERR(pas->tmd_inst); + if (ret == -ENODEV) { + pas->tmd_inst = NULL; + return 0; + } + return ret; + } + + return 0; +} + static int qcom_pas_probe(struct platform_device *pdev) { const struct qcom_pas_data *desc; @@ -852,12 +899,21 @@ static int qcom_pas_probe(struct platform_device *pdev) pas->pas_ctx->use_tzmem = rproc->has_iommu; pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; - ret = rproc_add(rproc); + + ret = qcom_pas_setup_tmd(pas); if (ret) goto remove_ssr_sysmon; + ret = rproc_add(rproc); + if (ret) + goto remove_setup_tmd; + return 0; +remove_setup_tmd: + if (pas->tmd_inst) + qmi_tmd_exit(pas->tmd_inst); + remove_ssr_sysmon: qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev); qcom_remove_sysmon_subdev(pas->sysmon); @@ -880,6 +936,9 @@ static void qcom_pas_remove(struct platform_device *pdev) { struct qcom_pas *pas = platform_get_drvdata(pdev); + if (pas->tmd_inst) + qmi_tmd_exit(pas->tmd_inst); + rproc_del(pas->rproc); qcom_q6v5_deinit(&pas->q6v5); From 66025bf1befff2a56ee290497032e28438e16b19 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 6 Feb 2026 02:44:05 +0530 Subject: [PATCH 0164/1058] FROMLIST: dt-bindings: hwmon: Add qcom,bcl-hwmon yaml bindings Add devicetree binding documentation for Qualcomm PMIC Battery Current Limiting (BCL) hardware monitor. The BCL hardware provides monitoring and alarm functionality for battery overcurrent and battery/system under voltage conditions. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260206-qcom-bcl-hwmon-v1-1-7b426f0b77a1@oss.qualcomm.com --- .../bindings/hwmon/qcom,bcl-hwmon.yaml | 128 ++++++++++++++++++ .../bindings/mfd/qcom,spmi-pmic.yaml | 4 + 2 files changed, 132 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml diff --git a/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml b/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml new file mode 100644 index 0000000000000..6ffadc4d28bcf --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/qcom,bcl-hwmon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SPMI PMIC Battery Current Limiting (BCL) Hardware Monitor + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: | + SPMI PMIC Battery Current Limiting (BCL) hardware provides monitoring and + alarm functionality for battery overcurrent and battery or system under + voltage conditions. It monitors battery voltage and current, and + can trigger interrupts when configurable thresholds are exceeded. + +properties: + compatible: + oneOf: + - description: v1 based BCL + items: + - enum: + - qcom,pm7250b-bcl + - qcom,pm8250b-bcl + - const: qcom,bcl-v1 + + - description: v2 based BCL + items: + - enum: + - qcom,pm8350b-bcl + - qcom,pm8350c-bcl + - const: qcom,bcl-v2 + + - description: v3 bmx based BCL + items: + - enum: + - qcom,pm8550b-bcl + - qcom,pm7550ba-bcl + - const: qcom,bcl-v3-bmx + + - description: v3 core based BCL + items: + - enum: + - qcom,pm8550-bc0l + - qcom,pm7550-bcl + - const: qcom,bcl-v3-core + + - description: v3 wb based BCL + items: + - enum: + - qcom,pmw5100-bcl + - const: qcom,bcl-v3-wb + + - description: v4 bmx based BCL + items: + - enum: + - qcom,pmih010-bcl + - const: qcom,bcl-v4-bmx + + - description: v4 bmx with different scale based BCL + items: + - enum: + - qcom,pmv010-bcl + - const: qcom,bcl-v4-pmv010 + + - description: v4 core based BCL + items: + - enum: + - qcom,pmh010-bcl + - const: qcom,bcl-v4-core + + - description: v4 wb based BCL + items: + - enum: + - qcom,pmw6100-bcl + - const: qcom,bcl-v4-wb + + reg: + maxItems: 1 + description: BCL base address in the SPMI PMIC register map + + interrupts: + minItems: 2 + maxItems: 2 + description: + BCL alarm interrupts for different threshold levels + + interrupt-names: + items: + - const: bcl-max-min + - const: bcl-critical + + overcurrent-thresholds-milliamp: + description: + Current thresholds in milliamperes for the two configurable current + alarm levels (max and critical). These values are used to override + default thresholds if a platform has different battery ocp specification. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + +required: + - compatible + - reg + - interrupts + - interrupt-names + +unevaluatedProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + sensor@1d00 { + compatible = "qcom,pm7250b-bcl", "qcom,bcl-v1"; + reg = <0x1d00>; + interrupts = <0x2 0x1d 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x1d 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "bcl-max-min", + "bcl-critical"; + overcurrent-thresholds-milliamp = <5500 6000>; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 644c42b5e2e57..0d4b44bc88c51 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -189,6 +189,10 @@ patternProperties: type: object $ref: /schemas/rtc/qcom-pm8xxx-rtc.yaml# + "^sensor@[0-9a-f]+$": + type: object + $ref: /schemas/hwmon/qcom,bcl-hwmon.yaml# + "^temp-alarm@[0-9a-f]+$": type: object $ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml# From 3122567e1af4ab6cf0748c2e49d3e1ab1c37a2cf Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 6 Feb 2026 02:44:06 +0530 Subject: [PATCH 0165/1058] FROMLIST: hwmon: Add Qualcomm PMIC BCL hardware monitor driver Add support for Qualcomm PMIC Battery Current Limiting (BCL) hardware monitor driver. The BCL peripheral is present in Qualcomm PMICs and provides real-time monitoring and protection against battery overcurrent and under voltage conditions. The driver monitors: - Battery voltage with configurable low voltage thresholds - Battery current with configurable high current thresholds - Two limit alarm interrupts (max/min, critical) The driver integrates with the Linux hwmon subsystem and provides standard hwmon attributes for monitoring battery conditions. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260206-qcom-bcl-hwmon-v1-2-7b426f0b77a1@oss.qualcomm.com --- MAINTAINERS | 9 + drivers/hwmon/Kconfig | 9 + drivers/hwmon/Makefile | 1 + drivers/hwmon/qcom-bcl-hwmon.c | 982 +++++++++++++++++++++++++++++++++ drivers/hwmon/qcom-bcl-hwmon.h | 311 +++++++++++ 5 files changed, 1312 insertions(+) create mode 100644 drivers/hwmon/qcom-bcl-hwmon.c create mode 100644 drivers/hwmon/qcom-bcl-hwmon.h diff --git a/MAINTAINERS b/MAINTAINERS index 829ffcb528f47..ad7b6703c7d93 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22100,6 +22100,15 @@ S: Maintained F: Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml F: drivers/net/wwan/qcom_bam_dmux.c +QUALCOMM BCL HARDWARE MONITOR DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-hwmon@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml +F: drivers/hwmon/qcom-bcl-hwmon.c +F: drivers/hwmon/qcom-bcl-hwmon.h + QUALCOMM BLUETOOTH DRIVER M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c2d3ff5fce82..251f5cc900b3b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1939,6 +1939,15 @@ config SENSORS_PWM_FAN This driver can also be built as a module. If so, the module will be called pwm-fan. +config SENSORS_QCOM_BCL + tristate "Qualcomm BCL hardware monitoring" + help + Say yes here to enable support for Qualcomm battery over current + and under voltage alarms monitor. + + This driver can also be built as a module. If so, the module + will be called qcom-bcl-hwmon. + config SENSORS_QNAP_MCU_HWMON tristate "QNAP MCU hardware monitoring" depends on MFD_QNAP_MCU diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 63effc0ab8d11..e0293c14a7cba 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -202,6 +202,7 @@ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o obj-$(CONFIG_SENSORS_PROM21_XHCI) += prom21-xhci.o obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o +obj-$(CONFIG_SENSORS_QCOM_BCL) += qcom-bcl-hwmon.o obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o diff --git a/drivers/hwmon/qcom-bcl-hwmon.c b/drivers/hwmon/qcom-bcl-hwmon.c new file mode 100644 index 0000000000000..9894b1d14d124 --- /dev/null +++ b/drivers/hwmon/qcom-bcl-hwmon.c @@ -0,0 +1,982 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm pmic BCL hardware driver for battery overcurrent and + * battery or system under voltage monitor + * + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcom-bcl-hwmon.h" + +ADD_BCL_HWMON_ALARM_MAPS(in, min, lcrit); +ADD_BCL_HWMON_ALARM_MAPS(curr, max, crit); + +/* Interrupt names for each alarm level */ +static const char * const bcl_int_names[ALARM_MAX] = { + [LVL0] = "bcl-max-min", + [LVL1] = "bcl-critical", +}; + +static const char * const bcl_channel_label[CHANNEL_MAX] = { + "BCL Voltage", + "BCL Current", +}; + +/* Common Reg Fields */ +static const struct reg_field common_reg_fields[COMMON_FIELD_MAX] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), +}; + +/* BCL Version/Modes specific fields */ +static const struct reg_field bcl_v1_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(MODE_CTL1, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v2_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 1), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_bmx_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_wb_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 3), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_core_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 5), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), +}; + +static const struct reg_field bcl_v4_bmx_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 15), +}; + +static const struct reg_field bcl_v4_wb_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 6), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 4), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 15), +}; + +static const struct reg_field bcl_v4_core_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 6), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 6), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), +}; + +/* V1 BMX and core */ +static const struct bcl_desc pm7250b_data = { + .reg_fields = bcl_v1_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 7, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 10000, + .default_scale_nu = 305180, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V2 BMX and core */ +static const struct bcl_desc pm8350_data = { + .reg_fields = bcl_v2_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 10000, + .default_scale_nu = 305180, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V3 BMX */ +static const struct bcl_desc pm8550b_data = { + .reg_fields = bcl_v3_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 12000, + .default_scale_nu = 366220, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V3 WB */ +static const struct bcl_desc pmw5100_data = { + .reg_fields = bcl_v3_wb_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .base = 800, + .max = 2000, + .step = 100, + .default_scale_nu = 61035, + .thresh_type = {ADC, INDEX}, + }, +}; + +/* V3 CORE */ +static const struct bcl_desc pm8550_data = { + .reg_fields = bcl_v3_core_reg_fields, + .num_reg_fields = F_CURR_MON_EN + 1, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .thresh_type = {INDEX, INDEX}, + }, +}; + +/* V4 BMX */ +static const struct bcl_desc pmih010_data = { + .reg_fields = bcl_v4_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 20000, + .default_scale_nu = 610370, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V4 WB */ +static const struct bcl_desc pmw6100_data = { + .reg_fields = bcl_v4_wb_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 1500, + .max = 4000, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .base = 900, + .max = 3300, + .step = 150, + .default_scale_nu = 152586, + .thresh_type = {ADC, INDEX}, + }, +}; + +/* V4 CORE */ +static const struct bcl_desc pmh010_data = { + .reg_fields = bcl_v4_core_reg_fields, + .num_reg_fields = F_CURR_MON_EN + 1, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 1500, + .max = 4000, + .step = 25, + .thresh_type = {INDEX, INDEX}, + }, +}; + +/* V4 BMX with different scale */ +static const struct bcl_desc pmv010_data = { + .reg_fields = bcl_v4_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 12000, + .default_scale_nu = 366220, + .thresh_type = {ADC, ADC}, + }, +}; + +/** + * bcl_convert_raw_to_milliunit - Convert raw value to milli unit + * @desc: BCL device descriptor + * @raw_val: Raw ADC value from hardware + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: value in milli unit + */ +static unsigned int bcl_convert_raw_to_milliunit(const struct bcl_desc *desc, int raw_val, + enum bcl_channel_type type, u8 field_width) +{ + u32 def_scale = desc->channel[type].default_scale_nu; + u32 lsb_weight = field_width > 8 ? 1 : 1 << field_width; + u32 scaling_factor = def_scale * lsb_weight; + + return div_s64((s64)raw_val * scaling_factor, 1000000); +} + +/** + * bcl_convert_milliunit_to_raw - Convert milli unit to raw value + * @desc: BCL device descriptor + * @ma_val: threshold value in milli unit + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: Raw ADC value for hardware + */ +static unsigned int bcl_convert_milliunit_to_raw(const struct bcl_desc *desc, int mval, + enum bcl_channel_type type, u8 field_width) +{ + u32 def_scale = desc->channel[type].default_scale_nu; + u32 lsb_weight = field_width > 8 ? 1 : 1 << field_width; + u32 scaling_factor = def_scale * lsb_weight; + + return div_s64((s64)mval * 1000000, scaling_factor); +} + +/** + * bcl_convert_milliunit_to_index - Convert milliunit to in or curr index + * @desc: BCL device descriptor + * @val: in or curr value in milli unit + * @type: type of the channel, in or curr + * + * Converts a value in milli unit to an index for BCL that use indexed thresholds. + * + * Return: Voltage index value + */ +static unsigned int bcl_convert_milliunit_to_index(const struct bcl_desc *desc, int val, + enum bcl_channel_type type) +{ + return div_s64((s64)val - desc->channel[type].base, desc->channel[type].step); +} + +/** + * bcl_convert_index_to_milliunit - Convert in or curr index to milli unit + * @desc: BCL device descriptor + * @val: index value + * @type: type of the channel, in or curr + * + * Converts an index value to milli unit for BCL that use indexed thresholds. + * + * Return: Voltage value in millivolts + */ +static unsigned int bcl_convert_index_to_milliunit(const struct bcl_desc *desc, int val, + enum bcl_channel_type type) +{ + return desc->channel[type].base + val * desc->channel[type].step; +} + +static int bcl_in_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + u32 raw_val; + + int thresh = clamp_val(value, desc->channel[IN].base, desc->channel[IN].max); + + if (desc->channel[IN].thresh_type[lvl] == ADC) + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, IN, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(desc, thresh, IN); + + return regmap_field_write(bcl->fields[F_IN_L0_THR + lvl], raw_val); +} + +static int bcl_curr_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + u32 raw_val; + + /* Clamp only to curr max */ + int thresh = clamp_val(value, value, desc->channel[CURR].max); + + if (desc->channel[CURR].thresh_type[lvl] == ADC) + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, CURR, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(desc, thresh, CURR); + + return regmap_field_write(bcl->fields[F_CURR_H0_THR + lvl], raw_val); +} + +static int bcl_in_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_IN_L0_THR + lvl, &raw_val); + if (ret) + return ret; + + if (desc->channel[IN].thresh_type[lvl] == ADC) + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, IN, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(desc, raw_val, IN); + + *out = thresh; + + return 0; +} + +static int bcl_curr_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_CURR_H0_THR + lvl, &raw_val); + if (ret) + return ret; + + if (desc->channel[CURR].thresh_type[lvl] == ADC) + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, CURR, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(desc, raw_val, CURR); + + *out = thresh; + + return 0; +} + +static int bcl_curr_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_CURR_INPUT, &raw_val); + if (ret) + return ret; + + /* + * The sensor sometime can read a value 0 if there are + * consecutive reads + */ + if (raw_val != 0) + bcl->last_curr_input = + bcl_convert_raw_to_milliunit(desc, raw_val, CURR, + desc->data_field_bits_size); + + *out = bcl->last_curr_input; + + return 0; +} + +static int bcl_in_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_IN_INPUT, &raw_val); + if (ret) + return ret; + + if (raw_val < GENMASK(desc->data_field_bits_size - 1, 0)) + bcl->last_in_input = + bcl_convert_raw_to_milliunit(desc, raw_val, IN, + desc->data_field_bits_size); + + *out = bcl->last_in_input; + + return 0; +} + +static int bcl_read_alarm_status(struct bcl_device *bcl, + enum bcl_limit_alarm lvl, long *status) +{ + int ret; + u32 raw_val = 0; + + ret = bcl_read_field_value(bcl, F_LVL0_ALARM + lvl, &raw_val); + if (ret) + return ret; + + *status = raw_val; + + return 0; +} + +static unsigned int bcl_get_version_major(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + bcl_read_field_value(bcl, F_V_MAJOR, &raw_val); + + return raw_val; +} + +static unsigned int bcl_get_version_minor(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + bcl_read_field_value(bcl, F_V_MINOR, &raw_val); + + return raw_val; +} + +static void bcl_hwmon_notify_event(struct bcl_device *bcl, enum bcl_limit_alarm alarm) +{ + if (bcl->in_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_in, + in_lvl_to_attr_map[alarm], 0); + if (bcl->curr_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_curr, + curr_lvl_to_attr_map[alarm], 0); +} + +static void bcl_alarm_enable_poll(struct work_struct *work) +{ + struct bcl_alarm_data *alarm = container_of(work, struct bcl_alarm_data, + alarm_poll_work.work); + struct bcl_device *bcl = alarm->device; + long status; + + guard(mutex)(&bcl->lock); + + if (bcl_read_alarm_status(bcl, alarm->type, &status)) + goto re_schedule; + + if (!status & !alarm->irq_enabled) { + bcl_enable_irq(alarm); + bcl_hwmon_notify_event(bcl, alarm->type); + return; + } + +re_schedule: + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); +} + +static irqreturn_t bcl_handle_alarm(int irq, void *data) +{ + struct bcl_alarm_data *alarm = data; + struct bcl_device *bcl = alarm->device; + long status; + + guard(mutex)(&bcl->lock); + + if (bcl_read_alarm_status(bcl, alarm->type, &status) || !status) + return IRQ_HANDLED; + + if (!bcl->hwmon_dev) + return IRQ_HANDLED; + + bcl_hwmon_notify_event(bcl, alarm->type); + + bcl_disable_irq(alarm); + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); + + dev_dbg(bcl->dev, "Irq:%d triggered for bcl type:%d\n", + irq, alarm->type); + + return IRQ_HANDLED; +} + +static umode_t bcl_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct bcl_device *bcl = data; + + switch (type) { + case hwmon_in: + if (!bcl->in_mon_enabled) + return 0; + switch (attr) { + case hwmon_in_input: + return bcl->in_input_enabled ? 0444 : 0; + case hwmon_in_label: + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + return 0444; + case hwmon_in_min: + case hwmon_in_lcrit: + return 0644; + default: + return 0; + } + case hwmon_curr: + if (!bcl->curr_mon_enabled) + return 0; + switch (attr) { + case hwmon_curr_input: + case hwmon_curr_label: + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + return 0444; + case hwmon_curr_max: + case hwmon_curr_crit: + return 0644; + default: + return 0; + } + default: + return 0; + } +} + +static int bcl_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + int ret = -EOPNOTSUPP; + + guard(mutex)(&bcl->lock); + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_min: + case hwmon_in_lcrit: + ret = bcl_in_thresh_write(bcl, val, in_attr_to_lvl_map[attr]); + break; + default: + ret = -EOPNOTSUPP; + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_max: + case hwmon_curr_crit: + ret = bcl_curr_thresh_write(bcl, val, curr_attr_to_lvl_map[attr]); + break; + default: + ret = -EOPNOTSUPP; + } + break; + default: + break; + } + + return ret; +} + +static int bcl_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *value) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + int ret; + + guard(mutex)(&bcl->lock); + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_input: + ret = bcl_in_input_read(bcl, value); + break; + case hwmon_in_min: + case hwmon_in_lcrit: + ret = bcl_in_thresh_read(bcl, in_attr_to_lvl_map[attr], value); + break; + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + ret = bcl_read_alarm_status(bcl, in_attr_to_lvl_map[attr], value); + break; + default: + ret = -EOPNOTSUPP; + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + ret = bcl_curr_input_read(bcl, value); + break; + case hwmon_curr_max: + case hwmon_curr_crit: + ret = bcl_curr_thresh_read(bcl, curr_attr_to_lvl_map[attr], value); + break; + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + ret = bcl_read_alarm_status(bcl, curr_attr_to_lvl_map[attr], value); + break; + default: + ret = -EOPNOTSUPP; + } + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int bcl_hwmon_read_string(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_in: + if (attr != hwmon_in_label) + break; + *str = bcl_channel_label[IN]; + return 0; + case hwmon_curr: + if (attr != hwmon_curr_label) + break; + *str = bcl_channel_label[CURR]; + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static const struct hwmon_ops bcl_hwmon_ops = { + .is_visible = bcl_hwmon_is_visible, + .read = bcl_hwmon_read, + .read_string = bcl_hwmon_read_string, + .write = bcl_hwmon_write, +}; + +static const struct hwmon_channel_info *bcl_hwmon_info[] = { + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_MIN | + HWMON_I_LCRIT | HWMON_I_MIN_ALARM | + HWMON_I_LCRIT_ALARM), + HWMON_CHANNEL_INFO(curr, + HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_MAX | + HWMON_C_CRIT | HWMON_C_MAX_ALARM | + HWMON_C_CRIT_ALARM), + NULL, +}; + +static const struct hwmon_chip_info bcl_hwmon_chip_info = { + .ops = &bcl_hwmon_ops, + .info = bcl_hwmon_info, +}; + +static int bcl_curr_thresh_update(struct bcl_device *bcl) +{ + int ret, i; + + if (!bcl->curr_thresholds[0]) + return 0; + + for (i = 0; i < ALARM_MAX; i++) { + ret = bcl_curr_thresh_write(bcl, bcl->curr_thresholds[i], i); + if (ret < 0) + return ret; + } + + return 0; +} + +static void bcl_hw_channel_mon_init(struct bcl_device *bcl) +{ + bcl->in_mon_enabled = bcl_in_monitor_enabled(bcl); + bcl->in_input_enabled = bcl_in_input_enabled(bcl); + bcl->curr_mon_enabled = bcl_curr_monitor_enabled(bcl); +} + +static int bcl_alarm_irq_init(struct platform_device *pdev, + struct bcl_device *bcl) +{ + int ret = 0, irq_num = 0, i = 0; + struct bcl_alarm_data *alarm; + + for (i = LVL0; i < ALARM_MAX; i++) { + alarm = &bcl->bcl_alarms[i]; + alarm->type = i; + alarm->device = bcl; + + ret = devm_delayed_work_autocancel(bcl->dev, &alarm->alarm_poll_work, + bcl_alarm_enable_poll); + if (ret) + return ret; + + irq_num = platform_get_irq_byname(pdev, bcl_int_names[i]); + if (irq_num <= 0) + continue; + + ret = devm_request_threaded_irq(&pdev->dev, irq_num, NULL, + bcl_handle_alarm, IRQF_ONESHOT, + bcl_int_names[i], alarm); + if (ret) { + dev_err(&pdev->dev, "Error requesting irq(%s).err:%d\n", + bcl_int_names[i], ret); + return ret; + } + alarm->irq = irq_num; + enable_irq_wake(alarm->irq); + alarm->irq_enabled = true; + } + + return 0; +} + +static int bcl_regmap_field_init(struct device *dev, struct bcl_device *bcl, + const struct bcl_desc *data) +{ + int i; + struct reg_field fields[F_MAX_FIELDS]; + + BUILD_BUG_ON(ARRAY_SIZE(common_reg_fields) != COMMON_FIELD_MAX); + + for (i = 0; i < data->num_reg_fields; i++) { + if (i < COMMON_FIELD_MAX) + fields[i] = common_reg_fields[i]; + else + fields[i] = data->reg_fields[i]; + + /* Need to adjust BCL base from regmap dynamically */ + fields[i].reg += bcl->base; + } + + return devm_regmap_field_bulk_alloc(dev, bcl->regmap, bcl->fields, + fields, data->num_reg_fields); +} + +static int bcl_get_device_property_data(struct platform_device *pdev, + struct bcl_device *bcl) +{ + struct device *dev = &pdev->dev; + int ret; + u32 reg; + + ret = device_property_read_u32(dev, "reg", ®); + if (ret < 0) + return ret; + + bcl->base = reg; + + device_property_read_u32_array(dev, "overcurrent-thresholds-milliamp", + bcl->curr_thresholds, 2); + return 0; +} + +static int bcl_probe(struct platform_device *pdev) +{ + struct bcl_device *bcl; + int ret; + + bcl = devm_kzalloc(&pdev->dev, sizeof(*bcl), GFP_KERNEL); + if (!bcl) + return -ENOMEM; + + bcl->dev = &pdev->dev; + bcl->desc = device_get_match_data(&pdev->dev); + if (!bcl->desc) + return -EINVAL; + + ret = devm_mutex_init(bcl->dev, &bcl->lock); + if (ret) + return ret; + + bcl->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!bcl->regmap) { + dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); + return -EINVAL; + } + + ret = bcl_get_device_property_data(pdev, bcl); + if (ret < 0) + return ret; + + ret = bcl_regmap_field_init(bcl->dev, bcl, bcl->desc); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to allocate regmap fields, err:%d\n", ret); + return ret; + } + + if (!bcl_hw_is_enabled(bcl)) + return -ENODEV; + + ret = bcl_curr_thresh_update(bcl); + if (ret < 0) + return ret; + + ret = bcl_alarm_irq_init(pdev, bcl); + if (ret < 0) + return ret; + + bcl_hw_channel_mon_init(bcl); + + dev_set_drvdata(&pdev->dev, bcl); + + bcl->hwmon_name = devm_hwmon_sanitize_name(&pdev->dev, + dev_name(bcl->dev)); + if (IS_ERR(bcl->hwmon_name)) { + dev_err(&pdev->dev, "Failed to sanitize hwmon name\n"); + return PTR_ERR(bcl->hwmon_name); + } + + bcl->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, + bcl->hwmon_name, + bcl, + &bcl_hwmon_chip_info, + NULL); + if (IS_ERR(bcl->hwmon_dev)) { + dev_err(&pdev->dev, "Failed to register hwmon device: %ld\n", + PTR_ERR(bcl->hwmon_dev)); + return PTR_ERR(bcl->hwmon_dev); + } + + dev_dbg(&pdev->dev, "BCL hwmon device with version: %u.%u registered\n", + bcl_get_version_major(bcl), bcl_get_version_minor(bcl)); + + return 0; +} + +static const struct of_device_id bcl_match[] = { + { + .compatible = "qcom,bcl-v1", + .data = &pm7250b_data, + }, { + .compatible = "qcom,bcl-v2", + .data = &pm8350_data, + }, { + .compatible = "qcom,bcl-v3-bmx", + .data = &pm8550b_data, + }, { + .compatible = "qcom,bcl-v3-wb", + .data = &pmw5100_data, + }, { + .compatible = "qcom,bcl-v3-core", + .data = &pm8550_data, + }, { + .compatible = "qcom,bcl-v4-bmx", + .data = &pmih010_data, + }, { + .compatible = "qcom,bcl-v4-wb", + .data = &pmw6100_data, + }, { + .compatible = "qcom,bcl-v4-core", + .data = &pmh010_data, + }, { + .compatible = "qcom,bcl-v4-pmv010", + .data = &pmv010_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, bcl_match); + +static struct platform_driver bcl_driver = { + .probe = bcl_probe, + .driver = { + .name = BCL_DRIVER_NAME, + .of_match_table = bcl_match, + }, +}; + +MODULE_AUTHOR("Manaf Meethalavalappu Pallikunhi "); +MODULE_DESCRIPTION("QCOM BCL HWMON driver"); +module_platform_driver(bcl_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/qcom-bcl-hwmon.h b/drivers/hwmon/qcom-bcl-hwmon.h new file mode 100644 index 0000000000000..28a7154d9486a --- /dev/null +++ b/drivers/hwmon/qcom-bcl-hwmon.h @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __QCOM_BCL_HWMON_H__ +#define __QCOM_BCL_HWMON_H__ + +#define BCL_DRIVER_NAME "qcom-bcl-hwmon" + +/* BCL common regmap offset */ +#define REVISION1 0x0 +#define REVISION2 0x1 +#define STATUS 0x8 +#define INT_RT_STS 0x10 +#define EN_CTL1 0x46 + +/* BCL GEN1 regmap offsets */ +#define MODE_CTL1 0x41 +#define VADC_L0_THR 0x48 +#define VCMP_L1_THR 0x49 +#define IADC_H0_THR 0x4b +#define IADC_H1_THR 0x4c +#define VADC_CONV_REQ 0x72 +#define IADC_CONV_REQ 0x82 +#define VADC_DATA1 0x76 +#define IADC_DATA1 0x86 + +/* BCL GEN3 regmap offsets */ +#define VCMP_CTL 0x44 +#define VCMP_L0_THR 0x47 +#define PARAM_1 0x0e +#define IADC_H1_THR_GEN3 0x4d + +#define BCL_IN_INC_MV 25 +#define BCL_ALARM_POLLING_MS 50 + +/** + * enum bcl_limit_alarm - BCL alarm threshold levels + * @LVL0: Level 0 alarm threshold (mapped to in_min_alarm or curr_max_alarm) + * @LVL1: Level 1 alarm threshold (mapped to in_lcrit_alarm or curr_crit_alarm) + * @ALARM_MAX: sentinel value + * + * Defines the three threshold levels for BCL monitoring. Each level corresponds + * to different severity of in or curr conditions. + */ +enum bcl_limit_alarm { + LVL0, + LVL1, + + ALARM_MAX, +}; + +/** + * enum bcl_channel_type - BCL supported sensor channel type + * @IN: in (voltage) channel + * @CURR: curr (current) channel + * @CHANNEL_MAX: sentinel value + * + * Defines the supported channel types for bcl. + */ +enum bcl_channel_type { + IN, + CURR, + + CHANNEL_MAX, +}; + +/** + * enum bcl_thresh_type - voltage or current threshold representation type + * @ADC: Raw ADC value representation + * @INDEX: Index-based voltage or current representation + * + * Specifies how voltage or current thresholds are stored and interpreted in + * registers. Some PMICs use raw ADC values while others use indexed values. + */ +enum bcl_thresh_type { + ADC, + INDEX, +}; + +/** + * enum bcl_fields - BCL register field identifiers + * @F_V_MAJOR: Major revision info field + * @F_V_MINOR: Minor revision info field + * @F_CTL_EN: Monitor enable control field + * @F_LVL0_ALARM: Level 0 alarm status field + * @F_LVL1_ALARM: Level 1 alarm status field + * @COMMON_FIELD_MAX: sentinel value for common fields + * @F_IN_MON_EN: voltage monitor enable control field + * @F_IN_L0_THR: voltage level 0 threshold field + * @F_IN_L1_THR: voltage level 1 threshold field + * @F_IN_INPUT_EN: voltage input enable control field + * @F_IN_INPUT: voltage input data field + * @F_CURR_MON_EN: current monitor enable control field + * @F_CURR_H0_THR: current level 0 threshold field + * @F_CURR_H1_THR: current level 1 threshold field + * @F_CURR_INPUT: current input data field + * @F_MAX_FIELDS: sentinel value + * + * Enumeration of all register fields used by the BCL driver for accessing + * registers through regmap fields. + */ +enum bcl_fields { + F_V_MAJOR, + F_V_MINOR, + + F_CTL_EN, + + /* common alarm for in and curr channel */ + F_LVL0_ALARM, + F_LVL1_ALARM, + + COMMON_FIELD_MAX, + + F_IN_MON_EN = COMMON_FIELD_MAX, + F_IN_L0_THR, + F_IN_L1_THR, + + F_IN_INPUT_EN, + F_IN_INPUT, + + F_CURR_MON_EN, + F_CURR_H0_THR, + F_CURR_H1_THR, + + F_CURR_INPUT, + + F_MAX_FIELDS +}; + +#define ADD_BCL_HWMON_ALARM_MAPS(_type, lvl0_attr, lvl1_attr) \ + \ +static const u8 _type##_attr_to_lvl_map[] = { \ + [hwmon_##_type##_##lvl0_attr] = LVL0, \ + [hwmon_##_type##_##lvl1_attr] = LVL1, \ + [hwmon_##_type##_##lvl0_attr##_alarm] = LVL0, \ + [hwmon_##_type##_##lvl1_attr##_alarm] = LVL1, \ +}; \ + \ +static const u8 _type##_lvl_to_attr_map[ALARM_MAX] = { \ + [LVL0] = hwmon_##_type##_##lvl0_attr##_alarm, \ + [LVL1] = hwmon_##_type##_##lvl1_attr##_alarm, \ +} + +/** + * struct bcl_channel_cfg - BCL channel related configuration + * @default_scale_nu: Default scaling factor in nano unit + * @base: Base threshold value in milli unit + * @max: Maximum threshold value in milli unit + * @step: step increment value between two indexed threshold value + * @thresh_type: Array specifying threshold representation type for each alarm level + * + * Contains hardware-specific configuration and scaling parameters for different + * channel(voltage and current).. + */ + +struct bcl_channel_cfg { + u32 default_scale_nu; + u32 base; + u32 max; + u32 step; + u8 thresh_type[ALARM_MAX]; +}; + +/** + * struct bcl_desc - BCL device descriptor + * @reg_fields: Array of register field definitions for this device variant + * @channel: Each channel specific(voltage or current) configuration + * @num_reg_fields: Number of register field definitions for this device variant + * @data_field_bits_size: data read register bit size + * @thresh_field_bits_size: lsb bit size those are not included in threshold register + * + * Contains hardware-specific configuration and scaling parameters for different + * BCL variants. Each PMIC model may have different register layouts and + * conversion factors. + */ + +struct bcl_desc { + const struct reg_field *reg_fields; + struct bcl_channel_cfg channel[CHANNEL_MAX]; + u8 num_reg_fields; + u8 data_field_bits_size; + u8 thresh_field_bits_size; +}; + +struct bcl_device; + +/** + * struct bcl_alarm_data - BCL alarm interrupt data + * @irq: IRQ number assigned to this alarm + * @irq_enabled: Flag indicating if IRQ is enabled + * @type: Alarm level type (LVL0, or LVL1) + * @device: Pointer to parent BCL device structure + * @alarm_poll_work: delayed_work to poll alarm status + * + * Stores interrupt-related information for each alarm threshold level. + * Used by the IRQ handler to identify which alarm triggered. + */ +struct bcl_alarm_data { + int irq; + bool irq_enabled; + enum bcl_limit_alarm type; + struct bcl_device *device; + struct delayed_work alarm_poll_work; +}; + +/** + * struct bcl_device - Main BCL device structure + * @dev: Pointer to device structure + * @regmap: Regmap for accessing PMIC registers + * @fields: Array of regmap fields for register access + * @bcl_alarms: Array of alarm data structures for each threshold level + * @lock: Mutex for protecting concurrent hardware access + * @in_mon_enabled: Flag indicating if voltage monitoring is enabled + * @curr_mon_enabled: Flag indicating if current monitoring is enabled + * @curr_thresholds: Current threshold values in milliamps from dt-binding(LVL0 and LVL1) + * @base: the BCL regbase offset from regmap + * @in_input_enabled: Flag indicating if voltage input reading is enabled + * @last_in_input: Last valid voltage input reading in millivolts + * @last_curr_input: Last valid current input reading in milliamps + * @desc: Pointer to device descriptor with hardware-specific parameters + * @hwmon_dev: Pointer to registered hwmon device + * @hwmon_name: Sanitized name for hwmon device + * + * Main driver structure containing all state and configuration for a BCL + * monitoring instance. Manages voltage and current monitoring, thresholds, + * and alarm handling. + */ +struct bcl_device { + struct device *dev; + struct regmap *regmap; + u16 base; + struct regmap_field *fields[F_MAX_FIELDS]; + struct bcl_alarm_data bcl_alarms[ALARM_MAX]; + struct mutex lock; + u32 curr_thresholds[ALARM_MAX]; + u32 last_in_input; + u32 last_curr_input; + bool in_mon_enabled; + bool curr_mon_enabled; + bool in_input_enabled; + const struct bcl_desc *desc; + struct device *hwmon_dev; + char *hwmon_name; +}; + +/** + * bcl_read_field_value - Read alarm status for a given level + * @bcl: BCL device structure + * @id: Index in bcl->fields[] + * @val: Pointer to store val + * + * Return: 0 on success or regmap error code + */ +static inline int bcl_read_field_value(const struct bcl_device *bcl, enum bcl_fields id, u32 *val) +{ + return regmap_field_read(bcl->fields[id], val); +} + +/** + * bcl_field_enabled - Generic helper to check if a regmap field is enabled + * @bcl: BCL device structure + * @field: Index in bcl->fields[] + * + * Return: true if field is non-zero, false otherwise + */ +static inline bool bcl_field_enabled(const struct bcl_device *bcl, enum bcl_fields id) +{ + int ret; + u32 val = 0; + + ret = regmap_field_read(bcl->fields[id], &val); + if (ret) + return false; + + return !!val; +} + +#define bcl_in_input_enabled(bcl) bcl_field_enabled(bcl, F_IN_INPUT_EN) +#define bcl_curr_monitor_enabled(bcl) bcl_field_enabled(bcl, F_CURR_MON_EN) +#define bcl_in_monitor_enabled(bcl) bcl_field_enabled(bcl, F_IN_MON_EN) +#define bcl_hw_is_enabled(bcl) bcl_field_enabled(bcl, F_CTL_EN) + +/** + * bcl_enable_irq - Generic helper to enable alarm irq + * @alarm: BCL level alarm data + */ +static inline void bcl_enable_irq(struct bcl_alarm_data *alarm) +{ + if (alarm->irq_enabled) + return; + alarm->irq_enabled = true; + enable_irq(alarm->irq); + enable_irq_wake(alarm->irq); +} + +/** + * bcl_disable_irq - Generic helper to disable alarm irq + * @alarm: BCL level alarm data + */ +static inline void bcl_disable_irq(struct bcl_alarm_data *alarm) +{ + if (!alarm->irq_enabled) + return; + alarm->irq_enabled = false; + disable_irq_nosync(alarm->irq); + disable_irq_wake(alarm->irq); +} + +#endif /* __QCOM_BCL_HWMON_H__ */ From ffd0ae636da733dd3a19d12ac9f6209d071e7b16 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Sat, 20 Jun 2026 02:09:08 +0530 Subject: [PATCH 0166/1058] dt-bindings: power: limits: Describe Qualcomm SPEL hardware The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various domains. Add a DeviceTree binding to describe the SPEL block on Qualcomm's SoC. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260620-qcom_spel_driver_upstream-v2-1-a3ee6837c18f@oss.qualcomm.com --- .../bindings/power/limits/qcom,spel.yaml | 47 +++++++++++++++++++ MAINTAINERS | 6 +++ 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/limits/qcom,spel.yaml diff --git a/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml new file mode 100644 index 0000000000000..4c6e6cbfbfe40 --- /dev/null +++ b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/limits/qcom,spel.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SoC Power and Electrical Limits (SPEL) + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: + The Qualcomm SPEL (SoC Power and Electrical Limits) provides hardware-based + power monitoring and limiting capabilities for various power domains in + Qualcomm SoCs. + +properties: + compatible: + const: qcom,glymur-spel + + reg: + maxItems: 3 + + reg-names: + items: + - const: config + - const: constraints + - const: nodes + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + power-limits@ef3b000 { + compatible = "qcom,glymur-spel"; + reg = <0x0ef3b000 0x1000>, + <0x0ef3d000 0x1000>, + <0x0ef3e000 0x1000>; + reg-names = "config", + "constraints", + "nodes"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index ad7b6703c7d93..772d29ee46e47 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22331,6 +22331,12 @@ S: Maintained F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml F: drivers/power/supply/qcom_smbx.c +QUALCOMM SPEL POWERCAP DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/limits/qcom,spel.yaml + QUALCOMM PPE DRIVER M: Luo Jie L: netdev@vger.kernel.org From d36b3ee3b5ce84165d974c7141b15c3b6a283691 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Sat, 20 Jun 2026 02:09:09 +0530 Subject: [PATCH 0167/1058] powercap: qcom: Add SPEL powercap driver The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various power domains including System, SoC, CPU clusters, GPU, and various other subsystems. The driver integrates with the Linux powercap framework, exposing SPEL capabilities through powercap sysfs interfaces. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260620-qcom_spel_driver_upstream-v2-2-a3ee6837c18f@oss.qualcomm.com --- MAINTAINERS | 1 + drivers/powercap/Kconfig | 13 + drivers/powercap/Makefile | 1 + drivers/powercap/qcom_spel.c | 776 +++++++++++++++++++++++++++++++++++ 4 files changed, 791 insertions(+) create mode 100644 drivers/powercap/qcom_spel.c diff --git a/MAINTAINERS b/MAINTAINERS index 772d29ee46e47..10b40310aef45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22336,6 +22336,7 @@ M: Manaf Meethalavalappu Pallikunhi L: linux-arm-msm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/power/limits/qcom,spel.yaml +F: drivers/powercap/qcom_spel.c QUALCOMM PPE DRIVER M: Luo Jie diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 03c4c796d9931..e3a47c6534999 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -93,4 +93,17 @@ config DTPM_DEVFREQ help This enables support for device power limitation based on energy model. + +config QCOM_SPEL + tristate "Qualcomm SPEL Powercap driver" + depends on ARM64 || COMPILE_TEST + help + This enables support for the Qualcomm SoC Power and Electrical + Limits (SPEL) hardware, which allows power limits to be + enforced and monitored on Qualcomm SoCs. + + SPEL provides energy monitoring and power capping for multiple + domains including system, SoC, CPU clusters, GPU, and various + other subsystems. + endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index 5ab0dce565b9a..8235fb9d3df60 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o obj-$(CONFIG_IDLE_INJECT) += idle_inject.o obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o +obj-$(CONFIG_QCOM_SPEL) += qcom_spel.o diff --git a/drivers/powercap/qcom_spel.c b/drivers/powercap/qcom_spel.c new file mode 100644 index 0000000000000..4dd91cf36ccca --- /dev/null +++ b/drivers/powercap/qcom_spel.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Qualcomm SPEL (SoC Power and Electrical Limits) Driver + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPEL register bitmasks */ +#define ENERGY_STATUS_MASK GENMASK(31, 0) + +#define POWER_LIMIT_MASK GENMASK(14, 0) +#define POWER_LIMIT_ENABLE BIT(31) + +#define TIME_WINDOW_MASK_L GENMASK(14, 0) +#define TIME_WINDOW_MASK_H GENMASK(22, 16) +#define TIME_WINDOW_MAX ((FIELD_MAX(TIME_WINDOW_MASK_H) << 15) | \ + FIELD_MAX(TIME_WINDOW_MASK_L)) + +#define ENERGY_UNIT_MASK GENMASK(19, 16) +#define TIME_UNIT_MASK GENMASK(11, 8) +#define POWER_UNIT_MASK GENMASK(2, 0) + +#define LIMITS_CAPABILITY_OFFSET 0x20 +#define ENERGY_RPT_UNIT_OFFSET 0x04 + +#define ENERGY_UNIT_SCALE 1000 + +#define SPEL_DOMAIN_NAME_LENGTH 16 + +/* Domain types */ +enum spel_domain_type { + SPEL_DOMAIN_SYS, + SPEL_DOMAIN_SOC, + SPEL_DOMAIN_CL0, + SPEL_DOMAIN_CL1, + SPEL_DOMAIN_CL2, + SPEL_DOMAIN_IGPU, + SPEL_DOMAIN_DGPU, + SPEL_DOMAIN_NSP, + SPEL_DOMAIN_MMCX, + SPEL_DOMAIN_INFRA, + SPEL_DOMAIN_DRAM, + SPEL_DOMAIN_MDM, + SPEL_DOMAIN_WLAN, + SPEL_DOMAIN_USB1, + SPEL_DOMAIN_USB2, + SPEL_DOMAIN_USB3, + SPEL_DOMAIN_MAX, +}; + +/* Power limit IDs */ +enum spel_power_limit_id { + POWER_LIMIT1, + POWER_LIMIT2, + POWER_LIMIT3, + POWER_LIMIT4, + POWER_LIMITS_MAX, +}; + +/* Unit types for conversion */ +enum unit_type { + POWER_UNIT, + ENERGY_UNIT, + TIME_UNIT, +}; + +/* Power limit operation types */ +enum pl_ops_type { + PL_LIMIT, + PL_TIME_WINDOW, +}; + +static const char * const pl_names[] = { + [POWER_LIMIT1] = "pl1", + [POWER_LIMIT2] = "pl2", + [POWER_LIMIT3] = "pl3", + [POWER_LIMIT4] = "pl4", +}; + +/** + * struct spel_domain_info - Domain configuration + * @name: Domain name + * @offset: Register offset in node base + */ +struct spel_domain_info { + const char *name; + u32 offset; +}; + +/* Domain configuration */ +static const struct spel_domain_info domain_info[SPEL_DOMAIN_MAX] = { + [SPEL_DOMAIN_SYS] = { "sys", 0x40 }, + [SPEL_DOMAIN_SOC] = { "soc", 0x00 }, + [SPEL_DOMAIN_CL0] = { "cl0", 0x5c }, + [SPEL_DOMAIN_CL1] = { "cl1", 0x60 }, + [SPEL_DOMAIN_CL2] = { "cl2", 0x64 }, + [SPEL_DOMAIN_IGPU] = { "igpu", 0x08 }, + [SPEL_DOMAIN_DGPU] = { "dgpu", 0x44 }, + [SPEL_DOMAIN_NSP] = { "nsp", 0x0c }, + [SPEL_DOMAIN_MMCX] = { "mmcx", 0x10 }, + [SPEL_DOMAIN_INFRA] = { "infra", 0x18 }, + [SPEL_DOMAIN_DRAM] = { "dram", 0x1c }, + [SPEL_DOMAIN_MDM] = { "mdm", 0x48 }, + [SPEL_DOMAIN_WLAN] = { "wlan", 0x4c }, + [SPEL_DOMAIN_USB1] = { "usb1", 0x50 }, + [SPEL_DOMAIN_USB2] = { "usb2", 0x54 }, + [SPEL_DOMAIN_USB3] = { "usb3", 0x58 }, +}; + +/** + * struct spel_constraint_info - Power limit constraint information + * @limit_offset: Register offset for power limit value + * @time_window_offset: Register offset for time window + * @supported_mask: Bit mask in capability register + * @domain_id: Domain this constraint applies to + * @pl_id: Power limit ID (PL1, PL2, etc.) + */ +struct spel_constraint_info { + u32 limit_offset; + u32 time_window_offset; + u32 supported_mask; + enum spel_domain_type domain_id; + int pl_id; +}; + +/* Constraint configuration */ +static const struct spel_constraint_info constraints[] = { + /* SYS domain constraints */ + { 0x10, 0x70, BIT(0), SPEL_DOMAIN_SYS, POWER_LIMIT1 }, + { 0x14, 0x74, BIT(1), SPEL_DOMAIN_SYS, POWER_LIMIT2 }, + { 0x18, 0x78, BIT(2), SPEL_DOMAIN_SYS, POWER_LIMIT3 }, + { 0x1c, 0x7c, BIT(3), SPEL_DOMAIN_SYS, POWER_LIMIT4 }, + /* SoC domain constraints */ + { 0x00, 0x60, BIT(4), SPEL_DOMAIN_SOC, POWER_LIMIT1 }, + { 0x04, 0x64, BIT(5), SPEL_DOMAIN_SOC, POWER_LIMIT2 }, + { 0x08, 0x68, BIT(6), SPEL_DOMAIN_SOC, POWER_LIMIT3 }, + { 0x0c, 0x6c, BIT(7), SPEL_DOMAIN_SOC, POWER_LIMIT4 }, +}; + +/** + * struct spel_domain - SPEL power domain + * @power_zone: Powercap zone + * @lock: Mutex protecting register access + * @sp: Parent sys domain + * @status_reg: Energy counter register + * @name: Domain name + * @id: Domain type ID + */ +struct spel_domain { + struct powercap_zone power_zone; + struct mutex lock; /* Protects register read/write operations */ + void *sp; + void __iomem *status_reg; + char name[SPEL_DOMAIN_NAME_LENGTH]; + enum spel_domain_type id; +}; + +/** + * struct spel_system - SPEL system + * @domains: Array of domains + * @power_zone: Parent powercap zone + * @node_base: Base address for node registers + * @constraint_base: Base address for constraint registers + * @config_base: Base address for config registers + * @control_type: Powercap control type + * @dev: Device pointer for logging + * @limits: Supported power limits per domain + * @power_unit: Power unit in microWatts (common for all domains) + * @energy_unit: Energy unit in nanoJoules (common for all domains) + * @time_unit: Time unit in microseconds (common for all domains) + */ +struct spel_system { + struct spel_domain *domains; + struct powercap_zone *power_zone; + void __iomem *node_base; + void __iomem *constraint_base; + void __iomem *config_base; + struct powercap_control_type *control_type; + struct device *dev; + int limits[SPEL_DOMAIN_MAX]; + unsigned int power_unit; + unsigned int energy_unit; + unsigned int time_unit; +}; + +#define power_zone_to_spel_domain(_zone) \ + container_of(_zone, struct spel_domain, power_zone) + +static bool is_pl_valid(struct spel_domain *sd, int pl) +{ + struct spel_system *sp = sd->sp; + + return !!(sp->limits[sd->id] & BIT(pl)); +} + +static int get_pl_ops_offset(struct spel_domain *sd, int pl, enum pl_ops_type pl_op) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(constraints); i++) { + const struct spel_constraint_info *ci = &constraints[i]; + + if (ci->domain_id == sd->id && ci->pl_id == pl) { + switch (pl_op) { + case PL_LIMIT: + return ci->limit_offset; + case PL_TIME_WINDOW: + return ci->time_window_offset; + default: + return -EOPNOTSUPP; + } + } + } + + return -EOPNOTSUPP; +} + +static u64 spel_unit_xlate(struct spel_domain *sd, enum unit_type type, + u64 value, int to_raw) +{ + struct spel_system *sp = sd->sp; + u64 units, scale; + + switch (type) { + case POWER_UNIT: + units = sp->power_unit; + scale = 1; + break; + case ENERGY_UNIT: + units = sp->energy_unit; + scale = ENERGY_UNIT_SCALE; + break; + case TIME_UNIT: + units = sp->time_unit; + scale = 1; + break; + default: + return value; + } + + if (to_raw) + return DIV_ROUND_CLOSEST_ULL(value * scale, units); + + value *= units; + return div64_u64(value, scale); +} + +static int spel_read_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, bool xlate, u64 *data) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 value; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + value = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + value = FIELD_GET(POWER_LIMIT_MASK, value); + if (xlate) + *data = spel_unit_xlate(sd, POWER_UNIT, value, 0); + else + *data = value; + break; + case PL_TIME_WINDOW: + /* Decode time window: bits [22:16] are upper 7 bits, [14:0] are lower 15 bits */ + value = (FIELD_GET(TIME_WINDOW_MASK_H, value) << 15) | + FIELD_GET(TIME_WINDOW_MASK_L, value); + if (xlate) + *data = spel_unit_xlate(sd, TIME_UNIT, value, 0); + else + *data = value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int spel_write_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, unsigned long long value) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 reg_val, new_val; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + new_val = spel_unit_xlate(sd, POWER_UNIT, value, 1); + if (new_val > FIELD_MAX(POWER_LIMIT_MASK)) + return -EINVAL; + reg_val = (reg_val & ~POWER_LIMIT_MASK) | FIELD_PREP(POWER_LIMIT_MASK, new_val); + + /* + * Enable/Disable PL based on the value: + * - If value is 0, disable the PL (clear enable bit) + * - If value is non-zero, enable the PL (set enable bit) + */ + if (new_val == 0) + reg_val &= ~POWER_LIMIT_ENABLE; + else + reg_val |= POWER_LIMIT_ENABLE; + + writel(reg_val, reg_addr); + return 0; + + case PL_TIME_WINDOW: + /* + * Encode time window: upper 7 bits to [22:16], lower 15 bits to [14:0] + */ + new_val = spel_unit_xlate(sd, TIME_UNIT, value, 1); + if (new_val > TIME_WINDOW_MAX) + return -EINVAL; + /* Read-modify-write to preserve other bits */ + reg_val = (reg_val & ~(TIME_WINDOW_MASK_H | TIME_WINDOW_MASK_L)) | + FIELD_PREP(TIME_WINDOW_MASK_H, new_val >> 15) | + FIELD_PREP(TIME_WINDOW_MASK_L, new_val); + writel(reg_val, reg_addr); + + /* + * Time window register update doesn't trigger firmware interrupt. + * Write to the PL register with current value to trigger the interrupt. + */ + offset = get_pl_ops_offset(sd, pl, PL_LIMIT); + if (offset >= 0) { + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + writel(reg_val, reg_addr); + } + return 0; + + default: + return -EINVAL; + } +} + +static int spel_get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 value; + + value = readl(sd->status_reg); + + *energy_raw = spel_unit_xlate(sd, ENERGY_UNIT, value, 0); + + return 0; +} + +static int spel_get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) +{ + struct spel_domain *sd = power_zone_to_spel_domain(pcd_dev); + + *energy = spel_unit_xlate(sd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); + + return 0; +} + +static int spel_release_zone(struct powercap_zone *power_zone) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + struct spel_system *sp = sd->sp; + + /* Free the domains array when the last zone (SYS domain) is released */ + if (sd->id == SPEL_DOMAIN_SYS) + kfree(sp->domains); + + return 0; +} + +static int spel_find_nr_power_limit(struct spel_domain *sd) +{ + int i, nr_pl = 0; + + for (i = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i)) + nr_pl++; + } + + return nr_pl; +} + +static const struct powercap_zone_ops zone_ops = { + .get_energy_uj = spel_get_energy_counter, + .get_max_energy_range_uj = spel_get_max_energy_counter, + .release = spel_release_zone, +}; + +static int spel_constraint_to_pl(struct spel_domain *sd, int cid) +{ + int i, id; + + for (i = 0, id = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i) && id++ == cid) + return i; + } + + return -EINVAL; +} + +static int spel_set_power_limit(struct powercap_zone *power_zone, int cid, + u64 power_limit) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_LIMIT, power_limit); +} + +static int spel_get_power_limit(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_LIMIT, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static int spel_set_time_window(struct powercap_zone *power_zone, int cid, + u64 window) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_TIME_WINDOW, window); +} + +static int spel_get_time_window(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_TIME_WINDOW, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static const char *spel_get_constraint_name(struct powercap_zone *power_zone, + int cid) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id >= 0 && id < ARRAY_SIZE(pl_names)) + return pl_names[id]; + + return NULL; +} + +static const struct powercap_zone_constraint_ops constraint_ops = { + .set_power_limit_uw = spel_set_power_limit, + .get_power_limit_uw = spel_get_power_limit, + .set_time_window_us = spel_set_time_window, + .get_time_window_us = spel_get_time_window, + .get_name = spel_get_constraint_name, +}; + +static void spel_init_domains(struct spel_system *sp) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + sd->sp = sp; + snprintf(sd->name, SPEL_DOMAIN_NAME_LENGTH, "%s", + domain_info[i].name); + sd->id = i; + sd->status_reg = sp->node_base + domain_info[i].offset; + + /* PL1 is always supported (required for powercap registration) */ + sp->limits[i] = BIT(POWER_LIMIT1); + } +} + +static void spel_update_unit(struct spel_system *sp) +{ + u32 value, shift; + + /* Read power_unit and time_unit from offset 0x0 */ + value = readl(sp->config_base); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: TIME_UNIT (4 bits, max 15), POWER_UNIT (3 bits, max 7). + */ + shift = FIELD_GET(POWER_UNIT_MASK, value); + sp->power_unit = 1000000 / (1 << shift); + + shift = FIELD_GET(TIME_UNIT_MASK, value); + /* + * Time window in register is in milliseconds. + */ + sp->time_unit = 1000 * (1 << shift); + + /* Read energy_unit from ENERGY_RPT_UNIT_OFFSET */ + value = readl(sp->config_base + ENERGY_RPT_UNIT_OFFSET); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: ENERGY_UNIT (4 bits, max 15). + */ + shift = FIELD_GET(ENERGY_UNIT_MASK, value); + sp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << shift); + + dev_dbg(sp->dev, "Units: energy=%dnJ, time=%dus, power=%duW\n", + sp->energy_unit, sp->time_unit, sp->power_unit); +} + +static void spel_detect_powerlimit(struct spel_domain *sd) +{ + struct spel_system *sp = sd->sp; + u32 capabilities; + int i, j; + + capabilities = readl(sp->config_base + LIMITS_CAPABILITY_OFFSET); + + /* + * Detect power limits from hardware capabilities. + * Start from index 1 (POWER_LIMIT2) since PL1 is always enabled in spel_init_domains(). + */ + for (i = 1; i < ARRAY_SIZE(pl_names); i++) { + for (j = 0; j < ARRAY_SIZE(constraints); j++) { + const struct spel_constraint_info *ci = &constraints[j]; + + if (ci->domain_id == sd->id && ci->pl_id == i) { + if (capabilities & ci->supported_mask) + sp->limits[sd->id] |= BIT(i); + break; + } + } + } +} + +static int spel_init_system(struct spel_system *sp, struct device *dev) +{ + int i, ret; + + /* Read unit configuration (common for all domains) */ + spel_update_unit(sp); + + sp->domains = kcalloc(ARRAY_SIZE(domain_info), + sizeof(struct spel_domain), GFP_KERNEL); + if (!sp->domains) + return -ENOMEM; + + spel_init_domains(sp); + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + ret = devm_mutex_init(dev, &sd->lock); + if (ret) { + dev_err(dev, "Failed to initialize mutex for domain %s\n", sd->name); + kfree(sp->domains); + return ret; + } + + spel_detect_powerlimit(sd); + } + + return 0; +} + +static int spel_register_powercap(struct spel_system *sp) +{ + struct spel_domain *sd; + struct powercap_zone *power_zone; + int nr_pl, ret, i; + + /* Register SYS domain as parent zone */ + sd = &sp->domains[SPEL_DOMAIN_SYS]; + nr_pl = spel_find_nr_power_limit(sd); + + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, sd->name, + NULL, &zone_ops, nr_pl, + &constraint_ops); + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power zone %s\n", + sd->name); + return PTR_ERR(power_zone); + } + sp->power_zone = power_zone; + + /* Register other domains as children */ + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct powercap_zone *parent; + + if (i == SPEL_DOMAIN_SYS) + continue; + + sd = &sp->domains[i]; + + /* SOC is child of SYS, others are children of SOC */ + if (i == SPEL_DOMAIN_SOC) + parent = sp->power_zone; + else + parent = &sp->domains[SPEL_DOMAIN_SOC].power_zone; + + nr_pl = spel_find_nr_power_limit(sd); + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, + sd->name, parent, + &zone_ops, nr_pl, + &constraint_ops); + + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power_zone %s\n", + sd->name); + ret = PTR_ERR(power_zone); + goto err_cleanup; + } + } + + return 0; + +err_cleanup: + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = i - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + return ret; +} + +static int spel_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spel_system *sp; + int ret; + + sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); + if (!sp) + return -ENOMEM; + + sp->dev = dev; + + /* Map config registers (units, capabilities) */ + sp->config_base = devm_platform_ioremap_resource_byname(pdev, "config"); + if (IS_ERR(sp->config_base)) + return PTR_ERR(sp->config_base); + + /* Map constraint registers (power limits) */ + sp->constraint_base = devm_platform_ioremap_resource_byname(pdev, "constraints"); + if (IS_ERR(sp->constraint_base)) + return PTR_ERR(sp->constraint_base); + + /* Map spel domain registers (energy counters) */ + sp->node_base = devm_platform_ioremap_resource_byname(pdev, "nodes"); + if (IS_ERR(sp->node_base)) + return PTR_ERR(sp->node_base); + + sp->control_type = powercap_register_control_type(NULL, "qcom-spel", + NULL); + if (IS_ERR(sp->control_type)) { + dev_err(dev, "Failed to register control type\n"); + return PTR_ERR(sp->control_type); + } + + /* Initialize system and domains */ + ret = spel_init_system(sp, dev); + if (ret) { + dev_err(dev, "Failed to initialize system\n"); + goto err_unregister_control; + } + + ret = spel_register_powercap(sp); + if (ret) { + dev_err(dev, "Failed to register powercap zones\n"); + if (!sp->power_zone) + kfree(sp->domains); + goto err_unregister_control; + } + + platform_set_drvdata(pdev, sp); + + return 0; + +err_unregister_control: + powercap_unregister_control_type(sp->control_type); + return ret; +} + +static void spel_remove(struct platform_device *pdev) +{ + struct spel_system *sp = platform_get_drvdata(pdev); + int i; + + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = ARRAY_SIZE(domain_info) - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + powercap_unregister_control_type(sp->control_type); +} + +static const struct of_device_id spel_of_match[] = { + { .compatible = "qcom,glymur-spel" }, + { } +}; +MODULE_DEVICE_TABLE(of, spel_of_match); + +static struct platform_driver spel_driver = { + .probe = spel_probe, + .remove = spel_remove, + .driver = { + .name = "qcom_spel", + .of_match_table = spel_of_match, + }, +}; + +module_platform_driver(spel_driver); + +MODULE_DESCRIPTION("Qualcomm SPEL Powercap Driver"); +MODULE_LICENSE("GPL"); From 1cc303d042350bbb1e4fc4494c33356769995308 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:53:01 +0530 Subject: [PATCH 0168/1058] FROMLIST: arm64: dts: qcom: talos: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in talos. Set up CDSP cooling by throttling the cdsp, when it reaches 105°C. Link: https://lore.kernel.org/linux-devicetree/20260609-qmi-tmd-v3-6-291a2ff4c634@oss.qualcomm.com/ Signed-off-by: Gaurav Kohli --- arch/arm64/boot/dts/qcom/talos.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 669d5df57aff8..1cd4797968e11 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -3833,6 +3833,9 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -5486,15 +5489,31 @@ }; q6-hvx-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 10>; trips { + q6_hvx_alert0: trip-point0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + q6-hvx-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&q6_hvx_alert0>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; mdm-core-thermal { From 47aab5e9cc5d84612ebeb1639c6f1666c115bb05 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:14 +0530 Subject: [PATCH 0169/1058] power: reset: reboot-mode: Remove devres based allocations Devres APIs are intended for use in drivers, and they should be avoided in shared subsystem code which is being used by multiple drivers. Avoid using devres based allocations in the reboot-mode subsystem and manually free the resources. Replace devm_kzalloc with kzalloc and handle memory cleanup explicitly. Fixes: 4fcd504edbf7 ("power: reset: add reboot mode driver") Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-1-46e085bca4cc@oss.qualcomm.com --- drivers/power/reset/reboot-mode.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index d20e44db05325..1226eb49bc62d 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -3,6 +3,8 @@ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd */ +#define pr_fmt(fmt) "reboot-mode: " fmt + #include #include #include @@ -180,16 +182,15 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) if (strncmp(prop->name, PREFIX, len)) continue; - info = devm_kzalloc(reboot->dev, sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto error; } if (of_property_read_u32(np, prop->name, &info->magic)) { - dev_err(reboot->dev, "reboot mode %s without magic number\n", - info->mode); - devm_kfree(reboot->dev, info); + pr_err("reboot mode %s without magic number\n", info->mode); + kfree(info); continue; } @@ -200,8 +201,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) } else if (info->mode[0] == '\0') { kfree_const(info->mode); ret = -EINVAL; - dev_err(reboot->dev, "invalid mode name(%s): too short!\n", - prop->name); + pr_err("invalid mode name(%s): too short!\n", prop->name); goto error; } @@ -218,6 +218,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) return 0; error: + kfree(info); reboot_mode_unregister(reboot); return ret; } @@ -261,12 +262,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo int reboot_mode_unregister(struct reboot_mode_driver *reboot) { struct mode_info *info; + struct mode_info *next; unregister_reboot_notifier(&reboot->reboot_notifier); reboot_mode_unregister_device(reboot); - list_for_each_entry(info, &reboot->head, list) + list_for_each_entry_safe(info, next, &reboot->head, list) { + list_del(&info->list); kfree_const(info->mode); + kfree(info); + } return 0; } From 236b923a70f6209afd6559149d652661cf4a49d9 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:15 +0530 Subject: [PATCH 0170/1058] power: reset: reboot-mode: Add firmware node based registration The reboot-mode driver does not have a strict requirement for device-based registration. It primarily uses the device's of_node to read mode- properties. Remove the dependency on struct device and introduce support for firmware node (fwnode) based registration. This enables drivers that are not associated with a struct device to leverage the reboot-mode framework. Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-2-46e085bca4cc@oss.qualcomm.com --- drivers/power/reset/reboot-mode.c | 17 ++++++++++++++--- include/linux/reboot-mode.h | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 1226eb49bc62d..e60b51987c254 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -165,17 +165,25 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) /** * reboot_mode_register - register a reboot mode driver * @reboot: reboot mode driver + * @fwnode: Firmware node with reboot-mode configuration * * Returns: 0 on success or a negative error code on failure. */ -int reboot_mode_register(struct reboot_mode_driver *reboot) +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode) { struct mode_info *info; + struct device_node *np; struct property *prop; - struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); int ret; + if (!fwnode) + return -EINVAL; + + np = to_of_node(fwnode); + if (!np) + return -EINVAL; + INIT_LIST_HEAD(&reboot->head); for_each_property_of_node(np, prop) { @@ -295,11 +303,14 @@ int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver **dr; int rc; + if (!reboot->dev || !reboot->dev->of_node) + return -EINVAL; + dr = devres_alloc(devm_reboot_mode_release, sizeof(*dr), GFP_KERNEL); if (!dr) return -ENOMEM; - rc = reboot_mode_register(reboot); + rc = reboot_mode_register(reboot, of_fwnode_handle(reboot->dev->of_node)); if (rc) { devres_free(dr); return rc; diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 4a2abb38d1d61..22f707ade4ba9 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -2,6 +2,8 @@ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ +#include + struct reboot_mode_driver { struct device *dev; struct list_head head; @@ -9,7 +11,7 @@ struct reboot_mode_driver { struct notifier_block reboot_notifier; }; -int reboot_mode_register(struct reboot_mode_driver *reboot); +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode); int reboot_mode_unregister(struct reboot_mode_driver *reboot); int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver *reboot); From 1cc96fbc9507343e167adf868fc0d9fca3291f7b Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:16 +0530 Subject: [PATCH 0171/1058] power: reset: reboot-mode: Add support for 64 bit magic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current reboot-mode supports a single 32-bit argument for any supported mode. Some reboot-mode based drivers may require passing two independent 32-bit arguments during a reboot sequence, for uses-cases, where a mode requires an additional argument. Such drivers may not be able to use the reboot-mode driver. For example, ARM PSCI vendor-specific resets, need two arguments for its operation – reset_type and cookie, to complete the reset operation. If a driver wants to implement this firmware-based reset, it cannot use reboot-mode framework. Introduce 64-bit magic values in reboot-mode driver to accommodate dual 32-bit arguments when specified via device tree. In cases, where no second argument is passed from device tree, keep the upper 32-bit of magic un-changed(0) to maintain backward compatibility. Update the current drivers using reboot-mode for a 64-bit magic value. Reviewed-by: Umang Chheda Reviewed-by: Nirmesh Kumar Singh Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-3-46e085bca4cc@oss.qualcomm.com --- drivers/power/reset/nvmem-reboot-mode.c | 11 ++++++++--- drivers/power/reset/qcom-pon.c | 11 ++++++++--- drivers/power/reset/reboot-mode.c | 19 +++++++++++++------ drivers/power/reset/syscon-reboot-mode.c | 11 ++++++++--- include/linux/reboot-mode.h | 3 ++- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index d260715fccf67..4479c874077c7 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -17,14 +17,19 @@ struct nvmem_reboot_mode { struct nvmem_cell *cell; }; -static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct nvmem_reboot_mode *nvmem_rbm; size_t buf_len; + u32 magic_32; void *buf; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len); @@ -35,7 +40,7 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, if (buf_len > sizeof(magic)) return -EINVAL; - ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + ret = nvmem_cell_write(nvmem_rbm->cell, &magic_32, sizeof(magic_32)); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index 7e108982a582e..d0ed9431a0231 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c @@ -27,17 +27,22 @@ struct qcom_pon { long reason_shift; }; -static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct qcom_pon *pon = container_of (reboot, struct qcom_pon, reboot_mode); + u32 magic_32; int ret; + if (magic > U32_MAX || (magic << pon->reason_shift) > U32_MAX) + return -EINVAL; + + magic_32 = magic << pon->reason_shift; + ret = regmap_update_bits(pon->regmap, pon->baseaddr + PON_SOFT_RB_SPARE, GENMASK(7, pon->reason_shift), - magic << pon->reason_shift); + magic_32); if (ret < 0) dev_err(pon->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index e60b51987c254..55bc2243c9931 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -21,7 +21,7 @@ struct mode_info { const char *mode; - u32 magic; + u64 magic; struct list_head list; }; @@ -73,8 +73,7 @@ static const struct class reboot_mode_class = { .dev_groups = reboot_mode_groups, }; -static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - const char *cmd) +static u64 get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; struct mode_info *info; @@ -106,7 +105,7 @@ static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; - unsigned int magic; + u64 magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd); @@ -175,6 +174,8 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle struct device_node *np; struct property *prop; size_t len = strlen(PREFIX); + u32 magic_arg1; + u32 magic_arg2; int ret; if (!fwnode) @@ -196,12 +197,18 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle goto error; } - if (of_property_read_u32(np, prop->name, &info->magic)) { - pr_err("reboot mode %s without magic number\n", info->mode); + if (of_property_read_u32(np, prop->name, &magic_arg1)) { + pr_err("reboot mode without magic number\n"); kfree(info); continue; } + if (of_property_read_u32_index(np, prop->name, 1, &magic_arg2)) + magic_arg2 = 0; + + info->magic = magic_arg2; + info->magic = (info->magic << 32) | magic_arg1; + info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM; diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index e0772c9f70f7a..3cbd000c51223 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c @@ -20,16 +20,21 @@ struct syscon_reboot_mode { u32 mask; }; -static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct syscon_reboot_mode *syscon_rbm; + u32 magic_32; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot); ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset, - syscon_rbm->mask, magic); + syscon_rbm->mask, magic_32); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 22f707ade4ba9..e0d3e8a54050a 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -3,11 +3,12 @@ #define __REBOOT_MODE_H__ #include +#include struct reboot_mode_driver { struct device *dev; struct list_head head; - int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); + int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; }; From 58a50817c85533d9869e4cc7fbb7ed5574125977 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:20 +0530 Subject: [PATCH 0172/1058] firmware: psci: Implement vendor-specific resets as reboot-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SoC vendors have different types of resets which are controlled through various hardware registers. For instance, Qualcomm SoC may have a requirement that reboot with “bootloader” command should reboot the device to bootloader flashing mode and reboot with “edl” should reboot the device into Emergency flashing mode. Setting up such reboots on Qualcomm devices can be inconsistent across SoC platforms and may require setting different HW registers, where some of these registers may not be accessible to HLOS. These knobs evolve over product generations and require more drivers. PSCI spec defines, SYSTEM_RESET2, vendor-specific reset which can help align this requirement. Add support for PSCI SYSTEM_RESET2, vendor-specific resets and align the implementation to allow user-space initiated reboots to trigger these resets. Implement the PSCI vendor-specific resets by registering to the reboot-mode framework. As psci init is done at early kernel init, reboot-mode registration cannot be done at the time of psci init. This is because reboot-mode creates a “reboot-mode” class for exposing sysfs, which can fail at early kernel init. To overcome this, introduce a late_initcall to register PSCI vendor-specific resets as reboot modes. Implement a reboot-mode write function that sets reset_type and cookie values during the reboot notifier callback. Introduce a firmware-based call for SYSTEM_RESET2 vendor-specific reset in the psci_sys_reset path, using reset_type and cookie if supported by secure firmware. Register a panic notifier and clear vendor_reset valid status during panic. This is needed for any kernel panic that occurs post reboot_notifiers. By using the above implementation, userspace will be able to issue such resets using the reboot() system call with the "*arg" parameter as a string based command. The commands can be defined in PSCI device tree node under “reboot-mode” and are based on the reboot-mode based commands. Reviewed-by: Umang Chheda Reviewed-by: Kathiravan Thirumoorthy Reviewed-by: Nirmesh Kumar Singh Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-7-46e085bca4cc@oss.qualcomm.com --- drivers/firmware/psci/Kconfig | 2 + drivers/firmware/psci/psci.c | 91 ++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/psci/Kconfig b/drivers/firmware/psci/Kconfig index 97944168b5e66..93ff7b071a0c3 100644 --- a/drivers/firmware/psci/Kconfig +++ b/drivers/firmware/psci/Kconfig @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config ARM_PSCI_FW bool + select POWER_RESET + select REBOOT_MODE config ARM_PSCI_CHECKER bool "ARM PSCI checker" diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e73bae6cb23a3..82f99c7a410f9 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -8,15 +8,18 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -51,6 +54,24 @@ static int resident_cpu = -1; struct psci_operations psci_ops; static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE; +struct psci_vendor_sysreset2 { + u32 reset_type; + u32 cookie; + bool valid; +}; + +static struct psci_vendor_sysreset2 vendor_reset; + +static int psci_panic_event(struct notifier_block *nb, unsigned long v, void *p) +{ + vendor_reset.valid = false; + return NOTIFY_DONE; +} + +static struct notifier_block psci_panic_block = { + .notifier_call = psci_panic_event +}; + bool psci_tos_resident_on(int cpu) { return cpu == resident_cpu; @@ -309,7 +330,10 @@ static int get_set_conduit_method(const struct device_node *np) static int psci_sys_reset(struct notifier_block *nb, unsigned long action, void *data) { - if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && + if (vendor_reset.valid && psci_system_reset2_supported) { + invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), vendor_reset.reset_type, + vendor_reset.cookie, 0); + } else if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { /* * reset_type[31] = 0 (architectural) @@ -557,6 +581,71 @@ static const struct platform_suspend_ops psci_suspend_ops = { .begin = psci_system_suspend_begin, }; +static int psci_set_vendor_sys_reset2(struct reboot_mode_driver *reboot, u64 magic) +{ + u32 magic_32; + + if (psci_system_reset2_supported) { + magic_32 = magic & GENMASK(31, 0); + vendor_reset.reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic_32; + vendor_reset.cookie = (magic >> 32) & GENMASK(31, 0); + vendor_reset.valid = true; + } + + return NOTIFY_DONE; +} + +static int __init psci_init_vendor_reset(void) +{ + struct reboot_mode_driver *reboot; + struct device_node *psci_np; + struct device_node *np; + int ret; + + if (!psci_system_reset2_supported) + return -EINVAL; + + psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0"); + if (!psci_np) + return -ENODEV; + + np = of_find_node_by_name(psci_np, "reboot-mode"); + if (!np) { + of_node_put(psci_np); + return -ENODEV; + } + + ret = atomic_notifier_chain_register(&panic_notifier_list, &psci_panic_block); + if (ret) + goto err_notifier; + + reboot = kzalloc(sizeof(*reboot), GFP_KERNEL); + if (!reboot) { + ret = -ENOMEM; + goto err_kzalloc; + } + + reboot->write = psci_set_vendor_sys_reset2; + + ret = reboot_mode_register(reboot, of_fwnode_handle(np)); + if (ret) + goto err_register; + + of_node_put(psci_np); + of_node_put(np); + return 0; + +err_register: + kfree(reboot); +err_kzalloc: + atomic_notifier_chain_unregister(&panic_notifier_list, &psci_panic_block); +err_notifier: + of_node_put(psci_np); + of_node_put(np); + return ret; +} +late_initcall(psci_init_vendor_reset) + static void __init psci_init_system_reset2(void) { int ret; From 26436631b379f35ea694b57d57654b554a06b197 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 8 May 2026 09:36:34 +0530 Subject: [PATCH 0173/1058] WORKAROUND: power: reset: reboot-mode: fix NULL deref when dev is not set reboot_mode_create_device() and reboot_mode_unregister_device() unconditionally dereference reboot->dev->driver->name to name the sysfs device. psci_init_vendor_reset() allocates a reboot_mode_driver with kzalloc (so reboot->dev == NULL) and never sets reboot->dev, causing a NULL pointer dereference at boot: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000068 pc : reboot_mode_register+0x334/0x3b8 psci_init_vendor_reset+0xdc/0x128 Kernel panic - not syncing: Oops: Fatal exception The offset 0x68 is the 'driver' pointer inside struct device on arm64, confirming that reboot->dev itself is NULL. Fix this by adding a 'name' field to struct reboot_mode_driver. reboot_mode_create_device() and reboot_mode_unregister_device() now prefer reboot->name; they fall back to reboot->dev->driver->name only when reboot->name is NULL, and return -EINVAL / return early if neither source is available. Set reboot->name = "psci" in psci_init_vendor_reset() so the sysfs device is correctly named. Existing device-based callers (nvmem-reboot-mode, syscon-reboot-mode, qcom-pon) are unaffected: they set reboot->dev before calling devm_reboot_mode_register(), so the fallback path is taken as before. Fixes: cfaf0a90789a ("power: reset: reboot-mode: Expose sysfs for registered reboot_modes") Fixes: 614b17a3ce6e ("firmware: psci: Implement vendor-specific resets as reboot-mode") Reported-by: LAVA job 91409 Signed-off-by: Salendarsingh Gaud --- drivers/firmware/psci/psci.c | 1 + drivers/power/reset/reboot-mode.c | 20 ++++++++++++++++++-- include/linux/reboot-mode.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index 82f99c7a410f9..158a0a1b9b879 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -626,6 +626,7 @@ static int __init psci_init_vendor_reset(void) } reboot->write = psci_set_vendor_sys_reset2; + reboot->name = "psci"; ret = reboot_mode_register(reboot, of_fwnode_handle(np)); if (ret) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 55bc2243c9931..0b9179100335f 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -120,8 +120,16 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) struct reboot_mode_sysfs_data *priv; struct mode_info *sysfs_info; struct mode_info *info; + const char *dev_name; int ret; + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return -EINVAL; + dev_name = reboot->dev->driver->name; + } + priv = kzalloc_obj(*priv, GFP_KERNEL); if (!priv) return -ENOMEM; @@ -147,7 +155,7 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) priv->reboot_mode_device = device_create(&reboot_mode_class, NULL, 0, (void *)priv, "%s", - reboot->dev->driver->name); + dev_name); if (IS_ERR(priv->reboot_mode_device)) { ret = PTR_ERR(priv->reboot_mode_device); goto error; @@ -253,8 +261,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo { struct reboot_mode_sysfs_data *priv; struct device *reboot_mode_device; + const char *dev_name; + + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return; + dev_name = reboot->dev->driver->name; + } - reboot_mode_device = class_find_device(&reboot_mode_class, NULL, reboot->dev->driver->name, + reboot_mode_device = class_find_device(&reboot_mode_class, NULL, dev_name, reboot_mode_match_by_name); if (!reboot_mode_device) diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index e0d3e8a54050a..56581199af234 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -7,6 +7,7 @@ struct reboot_mode_driver { struct device *dev; + const char *name; struct list_head head; int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; From 34c1d030a705a287c3c4018410084500867677de Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 3 Apr 2026 09:38:36 +0530 Subject: [PATCH 0174/1058] FROMLIST: cpuidle: Deny idle entry when CPU already have IPI interrupt pending CPU can get IPI interrupt from another CPU while it is executing cpuidle_select() or about to execute same. The selection do not account for pending interrupts and may continue to enter selected idle state only to exit immediately. Example trace collected when there is cross CPU IPI. [000] 154.892148: sched_waking: comm=sugov:4 pid=491 prio=-1 target_cpu=007 [000] 154.892148: ipi_raise: target_mask=00000000,00000080 (Function call interrupts) [007] 154.892162: cpu_idle: state=2 cpu_id=7 [007] 154.892208: cpu_idle: state=4294967295 cpu_id=7 [007] 154.892211: irq_handler_entry: irq=2 name=IPI [007] 154.892211: ipi_entry: (Function call interrupts) [007] 154.892213: sched_wakeup: comm=sugov:4 pid=491 prio=-1 target_cpu=007 [007] 154.892214: ipi_exit: (Function call interrupts) This impacts performance and the above count increments. commit ccde6525183c ("smp: Introduce a helper function to check for pending IPIs") already introduced a helper function to check the pending IPIs and it is used in pmdomain governor to deny the cluster level idle state when there is a pending IPI on any of cluster CPUs. This however does not stop CPU to enter CPU level idle state. Make use of same at CPUidle to deny the idle entry when there is already IPI pending. With change observing glmark2 [1] off screen scores improving in the range of 25% to 30% on Qualcomm lemans-evk board which is arm64 based having two clusters each with 4 CPUs. [1] https://github.com/glmark2/glmark2 Link: https://lore.kernel.org/r/20260403-cpuidle_ipi-v2-1-b3e44b032e2c@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- drivers/cpuidle/cpuidle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2d2f40a2cb813..b876a1a72ec01 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -224,6 +224,9 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP); ktime_t time_start, time_end; + if (cpus_peek_for_pending_ipi(cpumask_of(dev->cpu))) + return -EBUSY; + instrumentation_begin(); /* From 747e94fc179b7c54135c6c6fb176496152f94e88 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 30 Jun 2026 14:40:00 +0530 Subject: [PATCH 0175/1058] WORKAROUND: Revert "irqchip/qcom-pdc: Use FIELD_GET() to extract bank index and bit position" This reverts commit 8766c87e9bb499b5e2b04b9f51f9e525d41c5b46. Signed-off-by: Maulik Shah --- drivers/irqchip/qcom-pdc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 2014dbb0bc43a..08eec00a9cfe7 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -27,8 +27,6 @@ /* Valid only on HW version < 3.2 */ #define IRQ_ENABLE_BANK 0x10 #define IRQ_ENABLE_BANK_MAX (IRQ_ENABLE_BANK + BITS_TO_BYTES(PDC_MAX_GPIO_IRQS)) -#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5) -#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0) #define IRQ_i_CFG 0x110 /* Valid only on HW version >= 3.2 */ @@ -111,8 +109,8 @@ static void pdc_enable_intr_bank(int pin_out, bool on) unsigned long enable; u32 index, mask; - index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out); - mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out); + index = pin_out / 32; + mask = pin_out % 32; enable = pdc_reg_read(IRQ_ENABLE_BANK, index); __assign_bit(mask, &enable, on); From 10b7d6148b34218a3f439f81c33c29bcf33efcce Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 30 Jun 2026 14:41:25 +0530 Subject: [PATCH 0176/1058] WORKAROUND: Revert "irqchip/qcom-pdc: Add PDC_VERSION() macro to describe version register fields" This reverts commit ef631c422f2cc3f5a8c0687364bfafec4f3d531c. Signed-off-by: Maulik Shah --- drivers/irqchip/qcom-pdc.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 08eec00a9cfe7..0b82306f8dd80 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -3,7 +3,6 @@ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ -#include #include #include #include @@ -32,18 +31,12 @@ /* Valid only on HW version >= 3.2 */ #define IRQ_i_CFG_IRQ_ENABLE 3 -#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) +#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) -#define PDC_VERSION_REG 0x1000 -#define PDC_VERSION_MAJOR GENMASK(23, 16) -#define PDC_VERSION_MINOR GENMASK(15, 8) -#define PDC_VERSION_STEP GENMASK(7, 0) -#define PDC_VERSION(maj, min, step) (FIELD_PREP(PDC_VERSION_MAJOR, (maj)) | \ - FIELD_PREP(PDC_VERSION_MINOR, (min)) | \ - FIELD_PREP(PDC_VERSION_STEP, (step))) +#define PDC_VERSION_REG 0x1000 /* Notable PDC versions */ -#define PDC_VERSION_3_2 PDC_VERSION(3, 2, 0) +#define PDC_VERSION_3_2 0x30200 struct pdc_pin_region { u32 pin_base; From 6271a70a290d922439b97be236f9f1688d00e133 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 30 Jun 2026 15:02:40 +0530 Subject: [PATCH 0177/1058] WORKAROUND: Revert "irqchip/qcom-pdc: Tighten ioremap clamp to single DRV region size" This reverts commit f1a5a0f4c0eab83299201129cffb7907d7dc99c6. Signed-off-by: Maulik Shah --- drivers/irqchip/qcom-pdc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 0b82306f8dd80..5f0da15b6fc2c 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -21,7 +21,7 @@ #include #define PDC_MAX_GPIO_IRQS 256 -#define PDC_DRV_SIZE 0x10000 +#define PDC_DRV_OFFSET 0x10000 /* Valid only on HW version < 3.2 */ #define IRQ_ENABLE_BANK 0x10 @@ -357,6 +357,7 @@ static int pdc_setup_pin_mapping(struct device_node *np) return 0; } +#define QCOM_PDC_SIZE 0x30000 static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent) { @@ -370,7 +371,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare if (of_address_to_resource(node, 0, &res)) return -EINVAL; - res_size = max_t(resource_size_t, resource_size(&res), PDC_DRV_SIZE); + res_size = max_t(resource_size_t, resource_size(&res), QCOM_PDC_SIZE); if (res_size > resource_size(&res)) pr_warn("%pOF: invalid reg size, please fix DT\n", node); @@ -383,7 +384,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare * region with the expected offset to preserve support for old DTs. */ if (of_device_is_compatible(node, "qcom,x1e80100-pdc")) { - pdc_prev_base = ioremap(res.start - PDC_DRV_SIZE, IRQ_ENABLE_BANK_MAX); + pdc_prev_base = ioremap(res.start - PDC_DRV_OFFSET, IRQ_ENABLE_BANK_MAX); if (!pdc_prev_base) { pr_err("%pOF: unable to map previous PDC DRV region\n", node); return -ENXIO; From 3d62cc5165642c8de3adcd06fe2c96be5f611c21 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 30 Jun 2026 14:42:20 +0530 Subject: [PATCH 0178/1058] WORKAROUND: Revert "irqchip/qcom-pdc: Split __pdc_enable_intr() into per-version helpers" This reverts commit 668f3382845b3751220c6fcdd4c4cda0c2f0c78f. Signed-off-by: Maulik Shah --- drivers/irqchip/qcom-pdc.c | 41 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 5f0da15b6fc2c..32b77fa93f730 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -97,37 +97,28 @@ static void pdc_x1e_irq_enable_write(u32 bank, u32 enable) pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable); } -static void pdc_enable_intr_bank(int pin_out, bool on) +static void __pdc_enable_intr(int pin_out, bool on) { unsigned long enable; - u32 index, mask; - index = pin_out / 32; - mask = pin_out % 32; + if (pdc_version < PDC_VERSION_3_2) { + u32 index, mask; - enable = pdc_reg_read(IRQ_ENABLE_BANK, index); - __assign_bit(mask, &enable, on); + index = pin_out / 32; + mask = pin_out % 32; - if (pdc_x1e_quirk) - pdc_x1e_irq_enable_write(index, enable); - else - pdc_reg_write(IRQ_ENABLE_BANK, index, enable); -} + enable = pdc_reg_read(IRQ_ENABLE_BANK, index); + __assign_bit(mask, &enable, on); -static void pdc_enable_intr_cfg(int pin_out, bool on) -{ - unsigned long enable = pdc_reg_read(IRQ_i_CFG, pin_out); - - __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on); - pdc_reg_write(IRQ_i_CFG, pin_out, enable); -} - -static void __pdc_enable_intr(int pin_out, bool on) -{ - if (pdc_version < PDC_VERSION_3_2) - pdc_enable_intr_bank(pin_out, on); - else - pdc_enable_intr_cfg(pin_out, on); + if (pdc_x1e_quirk) + pdc_x1e_irq_enable_write(index, enable); + else + pdc_reg_write(IRQ_ENABLE_BANK, index, enable); + } else { + enable = pdc_reg_read(IRQ_i_CFG, pin_out); + __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on); + pdc_reg_write(IRQ_i_CFG, pin_out, enable); + } } static void pdc_enable_intr(struct irq_data *d, bool on) From 84994641e239b3060e271b68764e9479ae872211 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:36 +0530 Subject: [PATCH 0179/1058] FROMLIST: dt-bindings: interrupt-controller: qcom,pdc: Document reg and QMP Document PDC reg to configure pass through or secondary controller mode for GPIO IRQs. Document QMP handle for action concerning global resources. Link: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-2-760c8593ce50@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- .../devicetree/bindings/interrupt-controller/qcom,pdc.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml index 8162a49d49a66..16f3e221fe845 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml @@ -65,6 +65,7 @@ properties: items: - description: PDC base register region - description: Edge or Level config register for SPI interrupts + - description: PDC config for pass through or secondary IRQ mode for GPIOs '#interrupt-cells': const: 2 @@ -85,6 +86,10 @@ properties: The tuples indicates the valid mapping of valid PDC ports and their hwirq mapping. + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM. + required: - compatible - reg From fc0d727e4c51d975828779968db4fa988fafaede Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:37 +0530 Subject: [PATCH 0180/1058] FROMLIST: irqchip/qcom-pdc: Configure PDC to pass through mode There are two modes PDC irqchip supports pass through mode and secondary controller mode. All PDC irqchip supports pass through mode in which both Direct SPIs and GPIO IRQs (as SPIs) are sent to GIC without latching at PDC. Newer PDCs (v3.0 onwards) also support additional secondary controller mode where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs still works same as pass through mode without latching at PDC even in secondary controller mode. All the SoCs so far default uses pass through mode with the exception of x1e. x1e PDC may be set to secondary controller mode for builds on CRD boards whereas it may be set to pass through mode for IoT-EVK. There is no way to read which current mode it is set to and make PDC work in respective mode as the read access is not opened up for non secure world. There is though write access opened up via SCM write API to set the mode. Configure PDC mode to pass through mode for all x1e based boards via SCM write. Link: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-3-760c8593ce50@oss.qualcomm.com Co-developed-by: Sneh Mankad Signed-off-by: Sneh Mankad Signed-off-by: Maulik Shah --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/qcom-pdc.c | 121 ++++++++++++++++++++++++++++++++++--- 2 files changed, 112 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 42f2278a702d0..d8a9af2ad8132 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -528,6 +528,7 @@ config GOLDFISH_PIC config QCOM_PDC tristate "Qualcomm PDC" depends on ARCH_QCOM + depends on QCOM_AOSS_QMP select IRQ_DOMAIN_HIERARCHY help Power Domain Controller driver to manage and configure wakeup diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 32b77fa93f730..578206b8a7e39 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #define PDC_MAX_GPIO_IRQS 256 #define PDC_DRV_OFFSET 0x10000 @@ -26,9 +28,11 @@ /* Valid only on HW version < 3.2 */ #define IRQ_ENABLE_BANK 0x10 #define IRQ_ENABLE_BANK_MAX (IRQ_ENABLE_BANK + BITS_TO_BYTES(PDC_MAX_GPIO_IRQS)) +#define IRQ_i_CFG_IRQ_MASK_3_0 3 #define IRQ_i_CFG 0x110 /* Valid only on HW version >= 3.2 */ +#define IRQ_i_CFG_IRQ_MASK_3_2 4 #define IRQ_i_CFG_IRQ_ENABLE 3 #define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) @@ -36,8 +40,11 @@ #define PDC_VERSION_REG 0x1000 /* Notable PDC versions */ +#define PDC_VERSION_3_0 0x30000 #define PDC_VERSION_3_2 0x30200 +#define PDC_PASS_THROUGH_MODE 0 + struct pdc_pin_region { u32 pin_base; u32 parent_base; @@ -97,6 +104,33 @@ static void pdc_x1e_irq_enable_write(u32 bank, u32 enable) pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable); } +/* + * The new mask bit controls whether the interrupt is to be forwarded to the + * parent GIC in secondary controller mode. Writing the mask is do not care + * when the PDC is set to pass through mode. + * + * As linux only makes so far make use of pass through mode set all IRQs + * masked during probe. + */ +static void __pdc_mask_intr(int pin_out, bool mask) +{ + unsigned long irq_cfg; + int mask_bit; + + /* Mask bit available from v3.0 */ + if (pdc_version < PDC_VERSION_3_0) + return; + + if (pdc_version < PDC_VERSION_3_2) + mask_bit = IRQ_i_CFG_IRQ_MASK_3_0; + else + mask_bit = IRQ_i_CFG_IRQ_MASK_3_2; + + irq_cfg = pdc_reg_read(IRQ_i_CFG, pin_out); + __assign_bit(mask_bit, &irq_cfg, mask); + pdc_reg_write(IRQ_i_CFG, pin_out, irq_cfg); +} + static void __pdc_enable_intr(int pin_out, bool on) { unsigned long enable; @@ -312,7 +346,6 @@ static const struct irq_domain_ops qcom_pdc_ops = { static int pdc_setup_pin_mapping(struct device_node *np) { int ret, n, i; - n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32)); if (n <= 0 || n % 3) return -EINVAL; @@ -341,21 +374,26 @@ static int pdc_setup_pin_mapping(struct device_node *np) if (ret) return ret; - for (i = 0; i < pdc_region[n].cnt; i++) + for (i = 0; i < pdc_region[n].cnt; i++) { __pdc_enable_intr(i + pdc_region[n].pin_base, 0); + __pdc_mask_intr(i + pdc_region[n].pin_base, true); + } } return 0; } -#define QCOM_PDC_SIZE 0x30000 +#define QCOM_PDC_SIZE 0x10000 static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent) { + static const char buf[64] = "{class: cx_mol, res: cx, val: mol}"; + unsigned int domain_flag = IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP; struct irq_domain *parent_domain, *pdc_domain; struct device_node *node = pdev->dev.of_node; resource_size_t res_size; struct resource res; + struct qmp *pdc_qmp; int ret; /* compat with old sm8150 DT which had very small region for PDC */ @@ -366,6 +404,13 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare if (res_size > resource_size(&res)) pr_warn("%pOF: invalid reg size, please fix DT\n", node); + pdc_base = ioremap(res.start, res_size); + if (!pdc_base) { + pr_err("%pOF: unable to map PDC registers\n", node); + ret = -ENXIO; + goto fail; + } + /* * PDC has multiple DRV regions, each one provides the same set of * registers for a particular client in the system. Due to a hardware @@ -382,15 +427,71 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare } pdc_x1e_quirk = true; - } - pdc_base = ioremap(res.start, res_size); - if (!pdc_base) { - pr_err("%pOF: unable to map PDC registers\n", node); - ret = -ENXIO; - goto fail; + /* + * There are two modes PDC irqchip can work in + * - pass through mode + * - secondary controller mode + * + * All PDC irqchip supports pass through mode in which both + * Direct SPIs and GPIO IRQs (as SPIs) are sent to GIC + * without latching at PDC. + * + * Newer PDCs (v3.0 onwards) also support additional + * secondary controller mode where PDC latches GPIO IRQs + * and sends to GIC as level type IRQ. Direct SPIs still + * works same as pass through mode without latching at PDC + * even in secondary controller mode. + * + * All the SoCs so far default uses pass through mode with + * the exception of x1e. + * + * x1e modes: + * + * x1e PDC may be set to secondary controller mode for + * builds on CRD boards whereas it may be set to pass + * through mode for IoT-EVK boards. + * + * There is no way to read which current mode it is set to + * and make PDC work in respective mode as the read access + * is not opened up for non secure world. There is though + * write access opened up via SCM write API to set the mode. + * + * Configure PDC mode to pass through mode for all x1e based + * boards. + * + * For successful write: + * - Nothing more to be done + * + * For unsuccessful write: + * - Inform TLMM to monitor GPIO IRQs (same as MPM) + * - Prevent SoC low power mode (CxPC) as PDC is not + * monitoring GPIO IRQs which may be needed to wake + * the SoC from low power mode. + */ + ret = of_address_to_resource(node, 2, &res); + if (ret) { + domain_flag = IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP; + goto skip_scm_write; + } + + ret = qcom_scm_io_writel(res.start, PDC_PASS_THROUGH_MODE); + if (ret) { + pdc_qmp = qmp_get(&pdev->dev); + if (IS_ERR(pdc_qmp)) { + ret = PTR_ERR(pdc_qmp); + goto fail; + } else { + ret = qmp_send(pdc_qmp, buf, sizeof(buf)); + qmp_put(pdc_qmp); + if (ret) + goto fail; + } + domain_flag = IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP; + } } +skip_scm_write: pdc_version = pdc_reg_read(PDC_VERSION_REG, 0); parent_domain = irq_find_host(parent); @@ -407,7 +508,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare } pdc_domain = irq_domain_create_hierarchy(parent_domain, - IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP, + domain_flag, PDC_MAX_GPIO_IRQS, of_fwnode_handle(node), &qcom_pdc_ops, NULL); From bb887016f3998f14184b38d1ae3ced78a6d80567 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 31 Dec 2025 15:48:45 +0530 Subject: [PATCH 0181/1058] FROMLIST: dt-bindings: interrupt-controller: qcom,pdc: Document x1p42100 PDC Purwa shares the Hamoa (X1E80100) PDC device, but the hardware register bug addressed in commit e9a48ea4d90b ("irqchip/qcom-pdc: Workaround hardware register bug on X1E80100") is already fixed in Purwa silicon. Hamoa compatible forces the software workaround. Add PDC compatible for purwa as "qcom,x1p42100-pdc" to remove the workaround from Purwa. Fixes: f08edb529916 ("arm64: dts: qcom: Add X1P42100 SoC and CRD") Link: https://lore.kernel.org/r/20251231-purwa_pdc-v1-1-2b4979dd88ad@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- .../devicetree/bindings/interrupt-controller/qcom,pdc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml index 16f3e221fe845..040b8d4f8ee9c 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml @@ -58,6 +58,7 @@ properties: - qcom,sm8650-pdc - qcom,sm8750-pdc - qcom,x1e80100-pdc + - qcom,x1p42100-pdc - const: qcom,pdc reg: From 1c5dff88065d12fc38ca02c21f9cce7f01342373 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Thu, 30 Apr 2026 10:12:18 +0530 Subject: [PATCH 0182/1058] FROMLIST: pci: quirks: Advertise D3cold capability for UPD720201 PCIe-to-USB bridge UPD720201 does not advertise D3cold support until firmware is loaded post pci enumeration. This results in upd blocking D3cold entry during system suspend and causing overall failure to enter XO shutdown. Hence, add a quirk to advertise D3cold PME capability since the HW actually supports and advertises it post firmware loading. Link: https://lore.kernel.org/all/20260430-d3cold_support-v1-1-6734f280c481@oss.qualcomm.com/ Signed-off-by: Sushrut Shree Trivedi --- drivers/pci/quirks.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b09f27f7846fc..f27db09e455ea 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6415,3 +6415,13 @@ static void pci_mask_replay_timer_timeout(struct pci_dev *pdev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9750, pci_mask_replay_timer_timeout); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9755, pci_mask_replay_timer_timeout); #endif + +/* + * Renesas PCIe-to-USB bridge UPD720201 does not advertise D3cold + * capability by default until firmware is loaded post-enumeration. + */ +static void quirk_enable_d3cold(struct pci_dev *dev) +{ + dev->pme_support = dev->pme_support | (1 << PCI_D3cold); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RENESAS, 0x0014, quirk_enable_d3cold); From 9a2e6cf543cb81f5b2993c7e06d68dbbc10becac Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:02 +0530 Subject: [PATCH 0183/1058] FROMLIST: Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq Power supply to the M.2 Bluetooth device attached to the host using M.2 connector is controlled using the 'uart' pwrseq device. So add support for getting the pwrseq device if the OF graph link is present. Once obtained, the existing pwrseq APIs can be used to control the power supplies of the M.2 card. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-7-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 2444471956197..135c79e696aef 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2445,6 +2446,18 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + /* + * OF graph link is only present for BT devices attached through + * the M.2 Key E connector. + */ + if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, + "uart"); + if (IS_ERR(qcadev->bt_power->pwrseq)) + return PTR_ERR(qcadev->bt_power->pwrseq); + break; + } + if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the From 061d759f6f95d5ea52c0d280715971b6c3a5d126 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:03 +0530 Subject: [PATCH 0184/1058] FROMLIST: Bluetooth: hci_qca: Rename 'power_ctrl_enabled' to 'bt_en_available' 'power_ctrl_enabled' flag is used to indicate the availability of the BT_EN GPIO in devicetree. But the naming causes confusion with the new pwrctrl framework. So rename it to 'bt_en_available' to make it clear and explicit. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-8-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Dmitry Baryshkov Reviewed-by: Bartosz Golaszewski Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 135c79e696aef..17f436484e1e7 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2393,7 +2393,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) struct hci_dev *hdev; const struct qca_device_data *data; int err; - bool power_ctrl_enabled = true; + bool bt_en_available = true; qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); if (!qcadev) @@ -2501,7 +2501,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || data->soc_type == QCA_WCN7850)) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); @@ -2539,7 +2539,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) } if (!qcadev->bt_en) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->susclk = devm_clk_get_optional_enabled_with_rate( &serdev->dev, NULL, SUSCLK_RATE_32KHZ); @@ -2557,7 +2557,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) hdev = qcadev->serdev_hu.hdev; - if (power_ctrl_enabled) { + if (bt_en_available) { hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); hdev->shutdown = qca_hci_shutdown; } From ebd808fbc5fcd2b79e89bec0a311f7bb417b020c Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:04 +0530 Subject: [PATCH 0185/1058] FROMLIST: Bluetooth: hci_qca: Set 'bt_en_available' based on W_DISABLE2# presence in M.2 connector Check if the M.2 connector supports the W_DISABLE2# property or not by querying the pwrseq provider's DT node. If not available, then set 'bt_en_available' flag to 'false'. This flag is used to set the HCI_QUIRK_NON_PERSISTENT_SETUP HCI quirk, which informs the HCI layer whether the shutdown() callback for the device can be triggered or not. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-9-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Bartosz Golaszewski Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 17f436484e1e7..e09debdb00a1b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2451,10 +2451,17 @@ static int qca_serdev_probe(struct serdev_device *serdev) * the M.2 Key E connector. */ if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + struct device *dev; + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, "uart"); if (IS_ERR(qcadev->bt_power->pwrseq)) return PTR_ERR(qcadev->bt_power->pwrseq); + + dev = pwrseq_to_device(qcadev->bt_power->pwrseq); + if (!device_property_present(dev, "w-disable2-gpios")) + bt_en_available = false; + break; } From e379f2d4671e3c30c78d9ddf954d49b6d394547a Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 4 Dec 2025 18:53:17 -0800 Subject: [PATCH 0186/1058] FROMLIST: phy: qcom: qmp-pcie: Add multiple power-domains support The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs in a bifurcated configuration. Each PHY has its own power domain (phy_gdsc) that must be powered on before initialization per hardware requirements. Current PHY power management assumes a single power domain per PHY, preventing proper setup for this dual-PHY scenario. Add support for multiple power domains by using devm_pm_domain_attach_list() to attach power domains manually, while maintaining compatibility with single power domain PHYs. Enable runtime PM to allow power domain control when the PCIe driver calls phy_power_on/phy_power_off: - Single power domain: QMP PHY platform device directly attaches to power domain and controls it during runtime resume/suspend - Multiple power domains: devm_pm_domain_attach_list() creates virtual devices as power domain suppliers, linked to the QMP PHY platform device as consumer This ensures power domains are properly attached and turned on/off for both single and multiple power domain configurations. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-2-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index d3effad7a074b..110832bdc82d7 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -3440,6 +3441,8 @@ struct qmp_pcie { struct clk_fixed_rate pipe_clk_fixed; struct clk_fixed_rate aux_clk_fixed; + + struct dev_pm_domain_list *pd_list; }; static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val) @@ -5481,6 +5484,16 @@ static int qmp_pcie_probe(struct platform_device *pdev) WARN_ON_ONCE(!qmp->cfg->pwrdn_ctrl); WARN_ON_ONCE(!qmp->cfg->phy_status); + ret = devm_pm_domain_attach_list(dev, NULL, &qmp->pd_list); + if (ret < 0 && ret != -EEXIST) { + dev_err(dev, "Failed to attach power domain\n"); + return ret; + } + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + ret = qmp_pcie_clk_init(qmp); if (ret) return ret; From a0130777be85a74103c7f1b2d10a36875b400846 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 23 Oct 2025 06:15:38 -0700 Subject: [PATCH 0187/1058] FROMLIST: phy: qcom: qmp-pcie: Support multiple nocsr resets Refactor nocsr reset handling to support multiple nocsr resets required for PHY configurations with bifurcated operation modes. The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs in bifurcation, where each PHY requires its own nocsr reset to be controlled simultaneously. The current implementation only supports a single nocsr reset per PHY configuration. Add num_nocsr and nocsr_list fields to struct qmp_phy_cfg to represent the number and names of a group of nocsr reset names. Initialize these fields for all PHYs that have nocsr resets, allowing the driver to correctly acquire multiple nocsr resets during probe and control them as an array by using reset_control_bulk APIs. The refactoring maintains backward compatibility for existing single nocsr reset configurations while enabling support for multi-PHY scenarios like Glymur's 8-lane bifurcation mode. Additionally, introduces x1e80100_qmp_gen3x2_pciephy_cfg as a separate configuration from sm8550_qmp_gen3x2_pciephy_cfg since the x1e80100 Gen3x2 PHY requires nocsr reset support while the sm8550 Gen3x2 PHY does not. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-3-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 85 +++++++++++++++++++++--- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 110832bdc82d7..bdcf74aefe680 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3387,6 +3387,11 @@ struct qmp_phy_cfg { /* resets to be requested */ const char * const *reset_list; int num_resets; + + /* nocsr resets to be requested */ + const char * const *nocsr_reset_list; + int num_nocsr_resets; + /* regulators to be requested */ const char * const *vreg_list; int num_vregs; @@ -3433,7 +3438,7 @@ struct qmp_pcie { int num_pipe_clks; struct reset_control_bulk_data *resets; - struct reset_control *nocsr_reset; + struct reset_control_bulk_data *nocsr_reset; struct regulator_bulk_data *vregs; struct phy *phy; @@ -3500,6 +3505,10 @@ static const char * const sdm845_pciephy_reset_l[] = { "phy", }; +static const char * const sm8550_pciephy_nocsr_reset_l[] = { + "phy_nocsr", +}; + static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = { .serdes = 0, .pcs = 0x1800, @@ -4483,6 +4492,8 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4515,6 +4526,8 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4615,6 +4628,35 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v5, + + .tbls = { + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl), + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v5_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .lanes = 2, @@ -4637,6 +4679,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4670,6 +4714,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4701,6 +4747,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4716,6 +4764,8 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4759,6 +4809,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), @@ -4775,6 +4827,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), @@ -4903,7 +4957,7 @@ static int qmp_pcie_init(struct phy *phy) } } - ret = reset_control_assert(qmp->nocsr_reset); + ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset assert failed\n"); goto err_assert_reset; @@ -4940,7 +4994,7 @@ static int qmp_pcie_exit(struct phy *phy) const struct qmp_phy_cfg *cfg = qmp->cfg; if (qmp->nocsr_reset) - reset_control_assert(qmp->nocsr_reset); + reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); else reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -4984,7 +5038,7 @@ static int qmp_pcie_power_on(struct phy *phy) if (ret) return ret; - ret = reset_control_deassert(qmp->nocsr_reset); + ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset deassert failed\n"); goto err_disable_pipe_clk; @@ -5133,14 +5187,25 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp) for (i = 0; i < cfg->num_resets; i++) qmp->resets[i].id = cfg->reset_list[i]; - ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, + qmp->resets); if (ret) return dev_err_probe(dev, ret, "failed to get resets\n"); - qmp->nocsr_reset = devm_reset_control_get_optional_exclusive(dev, "phy_nocsr"); - if (IS_ERR(qmp->nocsr_reset)) - return dev_err_probe(dev, PTR_ERR(qmp->nocsr_reset), - "failed to get no-csr reset\n"); + if (!cfg->num_nocsr_resets) + return 0; + qmp->nocsr_reset = devm_kcalloc(dev, cfg->num_nocsr_resets, + sizeof(*qmp->nocsr_reset), GFP_KERNEL); + if (!qmp->nocsr_reset) + return -ENOMEM; + + for (i = 0; i < cfg->num_nocsr_resets; i++) + qmp->nocsr_reset[i].id = cfg->nocsr_reset_list[i]; + + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets, + qmp->nocsr_reset); + if (ret) + return dev_err_probe(dev, ret, "failed to get no-csr reset\n"); return 0; } @@ -5660,7 +5725,7 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { .data = &sm8750_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy", - .data = &sm8550_qmp_gen3x2_pciephy_cfg, + .data = &x1e80100_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy", .data = &x1e80100_qmp_gen4x2_pciephy_cfg, From 2ba133340ee83791981e9ed3af364d642214022f Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 23 Oct 2025 06:15:39 -0700 Subject: [PATCH 0188/1058] FROMLIST: phy: qcom: qmp-pcie: Add Gen5 8-lanes mode for Glymur The third PCIe controller on Glymur SoC supports 8-lane operation via bifurcation of two PHYs (each requires separate power domian, resets and aux clk). Add dedicated reset/no_csr reset list ("phy_b", "phy_b_nocsr") and clock ("phy_b_aux") required for 8-lane operation. Introduce new glymur_qmp_gen5x8_pciephy_cfg configuration to enable PCIe Gen5 x8 mode. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-4-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 30 +++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index bdcf74aefe680..fb7b7008ead10 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3484,7 +3484,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) /* list of clocks required by phy */ static const char * const qmp_pciephy_clk_l[] = { - "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", + "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", "phy_b_aux", }; /* list of regulators */ @@ -3509,6 +3509,14 @@ static const char * const sm8550_pciephy_nocsr_reset_l[] = { "phy_nocsr", }; +static const char * const glymur_pciephy_reset_l[] = { + "phy", "phy_b" +}; + +static const char * const glymur_pciephy_nocsr_reset_l[] = { + "phy_nocsr", "phy_b_nocsr", +}; + static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = { .serdes = 0, .pcs = 0x1800, @@ -4838,6 +4846,23 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = { + .lanes = 8, + + .offsets = &qmp_pcie_offsets_v8_50, + + .reset_list = glymur_pciephy_reset_l, + .num_resets = ARRAY_SIZE(glymur_pciephy_reset_l), + .nocsr_reset_list = glymur_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + + .regs = pciephy_v8_50_regs_layout, + + .phy_status = PHYSTATUS_4_20, +}; + static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -5621,6 +5646,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { }, { .compatible = "qcom,glymur-qmp-gen5x4-pcie-phy", .data = &glymur_qmp_gen5x4_pciephy_cfg, + }, { + .compatible = "qcom,glymur-qmp-gen5x8-pcie-phy", + .data = &glymur_qmp_gen5x8_pciephy_cfg, }, { .compatible = "qcom,ipq6018-qmp-pcie-phy", .data = &ipq6018_pciephy_cfg, From ec405c892a7bede96799f42453a4e0281fad9447 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 26 Feb 2026 01:13:41 -0800 Subject: [PATCH 0189/1058] FROMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode The Glymur SoC has pcie3a and pcie3b PHYs that can operate in two modes: 1. Independent 4-lane mode: Each PHY operates as a separate PCIe Gen5 4-lane interface, compatible with qcom,glymur-qmp-gen5x4-pcie-phy 2. Bifurcation mode (8-lane): pcie3a phy acts as leader and pcie3b phy as follower to form a single 8-lane PCIe Gen5 interface In bifurcation mode, the hardware design requires controlling additional resources beyond the standard pcie3a PHY configuration: - pcie3b's aux_clk (phy_b_aux) - pcie3b's phy_gdsc power domain - pcie3b's bcr/nocsr reset Add qcom,glymur-qmp-gen5x8-pcie-phy compatible string to document this 8-lane bifurcation configuration. The phy_b_aux clock is used as the 6th clock instead of pipediv2, requiring the clock-names enum to be extended to support both [phy_b_aux, pipediv2] options at index 5. This follows the existing pattern used for [rchng, refgen] clocks at index 3. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-1-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- .../phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 108cf9dc86ea0..1fddbf9c82d42 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -20,6 +20,7 @@ properties: - qcom,eliza-qmp-gen3x2-pcie-phy - qcom,glymur-qmp-gen4x2-pcie-phy - qcom,glymur-qmp-gen5x4-pcie-phy + - qcom,glymur-qmp-gen5x8-pcie-phy - qcom,kaanapali-qmp-gen3x2-pcie-phy - qcom,qcs615-qmp-gen3x1-pcie-phy - qcom,qcs8300-qmp-gen4x2-pcie-phy @@ -70,20 +71,23 @@ properties: - const: ref - enum: [rchng, refgen] - const: pipe - - const: pipediv2 + - enum: [phy_b_aux, pipediv2] power-domains: - maxItems: 1 + minItems: 1 + maxItems: 2 resets: minItems: 1 - maxItems: 2 + maxItems: 4 reset-names: minItems: 1 items: - const: phy - const: phy_nocsr + - const: phy_b + - const: phy_b_nocsr vdda-phy-supply: true @@ -196,6 +200,7 @@ allOf: - qcom,eliza-qmp-gen3x2-pcie-phy - qcom,glymur-qmp-gen4x2-pcie-phy - qcom,glymur-qmp-gen5x4-pcie-phy + - qcom,glymur-qmp-gen5x8-pcie-phy - qcom,qcs8300-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x4-pcie-phy @@ -214,6 +219,17 @@ allOf: clock-names: minItems: 6 + - if: + properties: + compatible: + contains: + enum: + - qcom,glymur-qmp-gen5x8-pcie-phy + then: + properties: + power-domains: + minItems: 2 + - if: properties: compatible: @@ -238,11 +254,24 @@ allOf: reset-names: minItems: 2 else: - properties: - resets: - maxItems: 1 - reset-names: - maxItems: 1 + if: + properties: + compatible: + contains: + enum: + - qcom,glymur-qmp-gen5x8-pcie-phy + then: + properties: + resets: + minItems: 4 + reset-names: + minItems: 4 + else: + properties: + resets: + maxItems: 1 + reset-names: + maxItems: 1 - if: properties: From ee2b755196cdd5d8cb518516a8155d1a756c71e6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Tue, 12 May 2026 18:21:10 +0300 Subject: [PATCH 0190/1058] FROMLIST: media: iris: Add Gen2 firmware autodetect and fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Iris platforms support both Gen1 and Gen2 HFI firmware images. Update the firmware loading logic to handle this generically by preferring Gen2 when available, while safely falling back to Gen1 when required. The firmware loading logic is updated with the following priority: 1. Device Tree (`firmware-name`): If specified, load unconditionally. 2. Gen2 default : If no DT override exists, select the Gen2 firmware descriptor when present and attempt to load the corresponding firmware image. 3. Gen1 Fallback: If loading the Gen2 firmware fails and a Gen1 descriptor is available, retry with the Gen1 firmware image. When a platform provides both Gen1 and Gen2 firmware descriptors and the firmware is loaded via a DT override, the driver detects the firmware generation at runtime before authentication by inspecting the firmware data. The firmware is classified as Gen2 if the QC_IMAGE_VERSION_STRING starts with "vfw" or matches the "video-firmware.N.M" format with N >= 2. If a Gen1 firmware image is detected in this case, the driver switches to the Gen1 firmware descriptor and associated platform data so that the correct HFI implementation is used. This change makes firmware generation detection platform‑agnostic, preserves DT overrides, prefers newer Gen2 firmware when available, and maintains compatibility with platforms that only support Gen1. Link: https://lore.kernel.org/all/20260529-kodiak-gen2-support-v4-v6-2-9a81bfa797d9@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Co-developed-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- .../media/platform/qcom/iris/iris_firmware.c | 105 +++++++++++++++--- .../platform/qcom/iris/iris_platform_common.h | 6 +- .../platform/qcom/iris/iris_platform_vpu2.c | 11 +- .../platform/qcom/iris/iris_platform_vpu3x.c | 10 +- drivers/media/platform/qcom/iris/iris_probe.c | 4 - drivers/media/platform/qcom/iris/iris_vidc.c | 3 + 6 files changed, 106 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index 1a476146d7580..64a2170bf538a 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -16,20 +16,95 @@ #define MAX_FIRMWARE_NAME_SIZE 128 -static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) +/* Detect Gen2 firmware by scanning the blob for: + * QC_IMAGE_VERSION_STRING= + * and then checking: + * - version starts with "vfw", OR + * - version matches "video-firmware.N.M" with N >= 2 + */ + +static bool iris_detect_gen2_from_fwdata(const u8 *data, size_t size) +{ + const char *marker = "QC_IMAGE_VERSION_STRING="; + const size_t mlen = strlen(marker); + int major = 0, minor = 0; + char version_buf[64]; + size_t max; + + max = (size > mlen) ? size - mlen : 0; + for (size_t i = 0; i < max; i++) { + if (!memcmp(data + i, marker, mlen)) { + const char *found = (const char *)(data + i + mlen); + + strscpy(version_buf, found, sizeof(version_buf)); + if (!strncmp(version_buf, "vfw", 3)) + return true; + if (sscanf(version_buf, "video-firmware.%d.%d", &major, &minor) == 2 && + major >= 2) + return true; + break; + } + } + + return false; +} + +static const struct firmware *iris_detect_firmware(struct iris_core *core, + const char **fw_name) +{ + const struct firmware *firmware; + bool has_both_gens; + int ret; + + *fw_name = NULL; + if (core->iris_platform_data->firmware_desc_gen2) + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen2; + else if (core->iris_platform_data->firmware_desc_gen1) + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + else + return ERR_PTR(-EINVAL); + + has_both_gens = core->iris_platform_data->firmware_desc_gen2 && + core->iris_platform_data->firmware_desc_gen1; + + ret = of_property_read_string_index(dev_of_node(core->dev), "firmware-name", 0, fw_name); + if (ret) { + *fw_name = core->iris_firmware_desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret && has_both_gens) { + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + *fw_name = core->iris_firmware_desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + } + + return ret ? ERR_PTR(ret) : firmware; + } + + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret) + return ERR_PTR(ret); + + if (has_both_gens && + !iris_detect_gen2_from_fwdata((const u8 *)firmware->data, firmware->size)) { + dev_info(core->dev, "Gen1 FW detected in %s\n", *fw_name); + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + } + + return firmware; +} + +static int iris_load_fw_to_memory(struct iris_core *core) { const struct firmware *firmware = NULL; struct device *dev = core->dev; struct resource res; phys_addr_t mem_phys; + const char *fw_name; size_t res_size; ssize_t fw_size; void *mem_virt; int ret; - if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) - return -EINVAL; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); if (ret) return ret; @@ -37,9 +112,11 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) mem_phys = res.start; res_size = resource_size(&res); - ret = request_firmware(&firmware, fw_name, dev); - if (ret) - return ret; + firmware = iris_detect_firmware(core, &fw_name); + if (IS_ERR(firmware)) + return PTR_ERR(firmware); + + core->iris_firmware_data = core->iris_firmware_desc->firmware_data; fw_size = qcom_mdt_get_size(firmware); if (fw_size < 0 || res_size < (size_t)fw_size) { @@ -66,18 +143,12 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) int iris_fw_load(struct iris_core *core) { const struct tz_cp_config *cp_config; - const char *fwpath = NULL; int i, ret; - ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0, - &fwpath); - if (ret) - fwpath = core->iris_firmware_desc->fwname; - - ret = iris_load_fw_to_memory(core, fwpath); + ret = iris_load_fw_to_memory(core); if (ret) { - dev_err(core->dev, "firmware download failed\n"); - return -ENOMEM; + dev_err(core->dev, "firmware download failed %d\n", ret); + return ret; } ret = qcom_scm_pas_auth_and_reset(IRIS_PAS_ID); @@ -99,7 +170,7 @@ int iris_fw_load(struct iris_core *core) } } - return ret; + return 0; } int iris_fw_unload(struct iris_core *core) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index c9256f2323dc4..55a4fa3569852 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -289,11 +289,7 @@ struct iris_firmware_desc { }; struct iris_platform_data { - /* - * XXX: replace with gen1 / gen2 pointers once we have platforms - * supporting both firmware kinds. - */ - const struct iris_firmware_desc *firmware_desc; + const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2; const struct vpu_ops *vpu_ops; const struct icc_info *icc_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index 6e06a32822bbb..961dce2e6aa92 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -22,6 +22,12 @@ static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = { .fwname = "qcom/vpu/vpu20_p1.mbn", }; +static const struct iris_firmware_desc iris_vpu20_p1_gen2_s6_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu33_buf_size, + .fwname = "qcom/vpu/vpu20_p1_gen2_s6.mbn", +}; + static const struct iris_firmware_desc iris_vpu20_p4_gen1_desc = { .firmware_data = &iris_hfi_gen1_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -65,7 +71,8 @@ static const struct tz_cp_config tz_cp_config_vpu2[] = { }; const struct iris_platform_data sc7280_data = { - .firmware_desc = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen2 = &iris_vpu20_p1_gen2_s6_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), @@ -94,7 +101,7 @@ const struct iris_platform_data sc7280_data = { }; const struct iris_platform_data sm8250_data = { - .firmware_desc = &iris_vpu20_p4_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p4_gen1_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 2c63adbc55791..74626b35d9cb3 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -90,7 +90,7 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = { * - inst_caps to platform_inst_cap_qcs8300 */ const struct iris_platform_data qcs8300_data = { - .firmware_desc = &iris_vpu30_p4_s6_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_s6_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -119,7 +119,7 @@ const struct iris_platform_data qcs8300_data = { }; const struct iris_platform_data sm8550_data = { - .firmware_desc = &iris_vpu30_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -154,7 +154,7 @@ const struct iris_platform_data sm8550_data = { * - controller_rst_tbl to sm8650_controller_reset_table */ const struct iris_platform_data sm8650_data = { - .firmware_desc = &iris_vpu33_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu33_p4_gen2_desc, .vpu_ops = &iris_vpu33_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -185,7 +185,7 @@ const struct iris_platform_data sm8650_data = { }; const struct iris_platform_data sm8750_data = { - .firmware_desc = &iris_vpu35_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu35_p4_gen2_desc, .vpu_ops = &iris_vpu35_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -220,7 +220,7 @@ const struct iris_platform_data sm8750_data = { * - different num_vpp_pipe */ const struct iris_platform_data x1p42100_data = { - .firmware_desc = &iris_vpu30_p1_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p1_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index c2dcb50a27824..7fe31136df21b 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -251,8 +251,6 @@ static int iris_probe(struct platform_device *pdev) return core->irq; core->iris_platform_data = of_device_get_match_data(core->dev); - core->iris_firmware_desc = core->iris_platform_data->firmware_desc; - core->iris_firmware_data = core->iris_firmware_desc->firmware_data; core->ubwc_cfg = qcom_ubwc_config_get_data(); if (IS_ERR(core->ubwc_cfg)) @@ -271,8 +269,6 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - iris_session_init_caps(core); - ret = v4l2_device_register(dev, &core->v4l2_dev); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 14d63dc76c9ba..372408b894c19 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -9,6 +9,7 @@ #include #include +#include "iris_ctrls.h" #include "iris_vidc.h" #include "iris_instance.h" #include "iris_vdec.h" @@ -196,6 +197,8 @@ int iris_open(struct file *filp) goto fail_m2m_release; } + iris_session_init_caps(core); + if (inst->domain == DECODER) ret = iris_vdec_inst_init(inst); else if (inst->domain == ENCODER) From 8f986e3ceae388cee18c342fc99f6c1a17836c1c Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:00 +0300 Subject: [PATCH 0191/1058] FROMLIST: media: iris: Skip UBWC configuration when not supported UBWC configuration is not applicable to all SoCs. Add a check to avoid configuring UBWC during sys init on unsupported platforms. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-1-df3846e74347@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Reviewed-by: Vishnu Reddy Reviewed-by: Vikash Garodia Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c index 0d05dd2afc07d..6e04175eb904b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c @@ -140,6 +140,9 @@ void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_heade &payload, sizeof(u32)); + if (!ubwc->ubwc_enc_version) + return; + payload = qcom_ubwc_macrotile_mode(ubwc) ? 8 : 4; iris_hfi_gen2_create_packet(hdr, HFI_PROP_UBWC_MAX_CHANNELS, From e4c043f6445276e92e3b8c14aef4de8e2edacb60 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:01 +0300 Subject: [PATCH 0192/1058] FROMLIST: media: iris: Filter UBWC raw formats based on hardware capabilities The raw formats supported by Iris were previously advertised unconditionally, assuming UBWC support on all platforms. However, some platforms do not support UBWC which results in incorrect format capability exposure. Use the UBWC configuration provided by the platform to dynamically filter raw formats at runtime. If UBWC is not supported, UBWC-based formats are omitted from the advertised capability list, while linear formats remain available. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-2-df3846e74347@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Reviewed-by: Vishnu Reddy Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_vdec.c | 9 +++++++++ drivers/media/platform/qcom/iris/iris_venc.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 9e228b70420e4..7da43f312ba98 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -3,6 +3,7 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include @@ -71,6 +72,7 @@ static const u32 iris_vdec_formats_cap[] = { static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size, i; const u32 *fmt; @@ -82,6 +84,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_vdec_formats_cap; size = ARRAY_SIZE(iris_vdec_formats_cap); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; default: return false; @@ -110,6 +115,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size; const u32 *fmt; @@ -121,6 +127,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_vdec_formats_cap; size = ARRAY_SIZE(iris_vdec_formats_cap); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; default: return 0; diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c index a945992f63aa8..2cafbe9f8abb5 100644 --- a/drivers/media/platform/qcom/iris/iris_venc.c +++ b/drivers/media/platform/qcom/iris/iris_venc.c @@ -3,6 +3,7 @@ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include @@ -91,6 +92,7 @@ static const u32 iris_venc_formats_out[] = { static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size, i; const u32 *fmt; @@ -98,6 +100,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt = iris_venc_formats_out; size = ARRAY_SIZE(iris_venc_formats_out); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_venc_formats_cap; @@ -117,6 +122,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size; const u32 *fmt; @@ -124,6 +130,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt = iris_venc_formats_out; size = ARRAY_SIZE(iris_venc_formats_out); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_venc_formats_cap; From d4c2c8c900b8b3f96d620935843d3d0fbb28c200 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:02 +0300 Subject: [PATCH 0193/1058] FROMLIST: media: iris: Introduce set_preset_register as a vpu_op The set_preset_registers sequence is currently shared across all supported devices. Starting with Qualcomm QCM2290 (AR50LT), the register programming would differ. Move set_preset_register into a vpu_op to allow per-device customization. This change prepares the driver for upcoming hardware variants. No functional change so far for existing devices. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-3-df3846e74347@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Reviewed-by: Vishnu Reddy Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_vpu2.c | 1 + drivers/media/platform/qcom/iris/iris_vpu3x.c | 3 +++ drivers/media/platform/qcom/iris/iris_vpu4x.c | 1 + drivers/media/platform/qcom/iris/iris_vpu_common.c | 2 +- drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index b8714dcbad10a..2dc121a3f5e89 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -45,4 +45,5 @@ const struct vpu_ops iris_vpu2_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu2_calc_freq, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 3dad47be78b58..dc02ced1b9314 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -261,6 +261,7 @@ const struct vpu_ops iris_vpu3_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, }; const struct vpu_ops iris_vpu33_ops = { @@ -270,6 +271,7 @@ const struct vpu_ops iris_vpu33_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, }; const struct vpu_ops iris_vpu35_ops = { @@ -280,4 +282,5 @@ const struct vpu_ops iris_vpu35_ops = { .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 02e100a4045fc..f608a297d4a34 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -368,4 +368,5 @@ const struct vpu_ops iris_vpu4x_ops = { .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu4x_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index ab41da1f47c82..a49113b0da238 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -483,7 +483,7 @@ int iris_vpu_power_on(struct iris_core *core) iris_opp_set_rate(core->dev, freq); - iris_vpu_set_preset_registers(core); + core->iris_platform_data->vpu_ops->set_preset_registers(core); iris_vpu_interrupt_init(core); core->intr_status = 0; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 09799a375c142..21ed4c9bd5e34 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -22,6 +22,7 @@ struct vpu_ops { void (*program_bootup_registers)(struct iris_core *core); u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); int (*set_hwmode)(struct iris_core *core); + void (*set_preset_registers)(struct iris_core *core); }; int iris_vpu_boot_firmware(struct iris_core *core); From 14b2a6ca947499bbf8386f4a1a202a4d0ade9a92 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:03 +0300 Subject: [PATCH 0194/1058] FROMLIST: media: iris: Introduce interrupt_init as a vpu_op The interrupt_init sequence is currently shared across all supported devices. Starting with Qualcomm QCM2290 (AR50LT), the register programming would differ. Move interrupt_init into a vpu_op to allow per-device customization. This change prepares the driver for upcoming hardware variants. No functional change so far for existing devices. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-4-df3846e74347@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_vpu2.c | 1 + drivers/media/platform/qcom/iris/iris_vpu3x.c | 3 +++ drivers/media/platform/qcom/iris/iris_vpu4x.c | 1 + drivers/media/platform/qcom/iris/iris_vpu_common.c | 4 ++-- drivers/media/platform/qcom/iris/iris_vpu_common.h | 2 ++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index 2dc121a3f5e89..dd2eeae0d9eb8 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -46,4 +46,5 @@ const struct vpu_ops iris_vpu2_ops = { .calc_freq = iris_vpu2_calc_freq, .set_hwmode = iris_vpu_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index dc02ced1b9314..c3b760730c981 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -262,6 +262,7 @@ const struct vpu_ops iris_vpu3_ops = { .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; const struct vpu_ops iris_vpu33_ops = { @@ -272,6 +273,7 @@ const struct vpu_ops iris_vpu33_ops = { .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; const struct vpu_ops iris_vpu35_ops = { @@ -283,4 +285,5 @@ const struct vpu_ops iris_vpu35_ops = { .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index f608a297d4a34..90ccdc0d2a076 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -369,4 +369,5 @@ const struct vpu_ops iris_vpu4x_ops = { .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu4x_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index a49113b0da238..375bcd9234766 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -31,7 +31,7 @@ #define UC_REGION_ADDR (CPU_CS_BASE_OFFS + 0x64) #define UC_REGION_SIZE (CPU_CS_BASE_OFFS + 0x68) -static void iris_vpu_interrupt_init(struct iris_core *core) +void iris_vpu_interrupt_init(struct iris_core *core) { u32 mask_val; @@ -485,7 +485,7 @@ int iris_vpu_power_on(struct iris_core *core) core->iris_platform_data->vpu_ops->set_preset_registers(core); - iris_vpu_interrupt_init(core); + core->iris_platform_data->vpu_ops->interrupt_init(core); core->intr_status = 0; enable_irq(core->irq); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 21ed4c9bd5e34..9151545065cda 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -23,6 +23,7 @@ struct vpu_ops { u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); int (*set_hwmode)(struct iris_core *core); void (*set_preset_registers)(struct iris_core *core); + void (*interrupt_init)(struct iris_core *core); }; int iris_vpu_boot_firmware(struct iris_core *core); @@ -44,5 +45,6 @@ void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core); u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size); void iris_vpu_set_preset_registers(struct iris_core *core); +void iris_vpu_interrupt_init(struct iris_core *core); #endif From 9b6aa5d886aa91159abf2431128d6b5ab64f3c15 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:04 +0300 Subject: [PATCH 0195/1058] FROMLIST: media: iris: add vpu op hook to disable ARP buffer On AR50LT platforms AbsolutelyPerfectRouting (ARP) needs to be disabled so firmware can configure the ARP internal buffer as non-secure for encoder usage. In preparation of adding support for AR50LT platforms, add an optional disable_arp callback to the VPU ops and invoke it from core init and resume paths. No functional change for existing platforms. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-5-df3846e74347@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Reviewed-by: Vishnu Reddy Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_core.c | 4 ++++ drivers/media/platform/qcom/iris/iris_hfi_common.c | 4 ++++ drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 52bf56e517f91..bd22076f35576 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -45,6 +45,7 @@ static int iris_wait_for_system_response(struct iris_core *core) int iris_core_init(struct iris_core *core) { + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; int ret; mutex_lock(&core->lock); @@ -78,6 +79,9 @@ int iris_core_init(struct iris_core *core) if (ret) goto error_unload_fw; + if (vpu_ops->disable_arp) + vpu_ops->disable_arp(core); + core->iris_firmware_data->init_hfi_ops(core); ret = iris_hfi_core_init(core); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c index 8769ec61f1176..8f04f3793d9af 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c @@ -144,6 +144,7 @@ int iris_hfi_pm_suspend(struct iris_core *core) int iris_hfi_pm_resume(struct iris_core *core) { + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; const struct iris_hfi_sys_ops *ops = core->hfi_sys_ops; int ret; @@ -163,6 +164,9 @@ int iris_hfi_pm_resume(struct iris_core *core) if (ret) goto err_suspend_hw; + if (vpu_ops->disable_arp) + vpu_ops->disable_arp(core); + ret = ops->sys_interframe_powercollapse(core); if (ret) goto err_suspend_hw; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 9151545065cda..71d96921ed372 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -24,6 +24,7 @@ struct vpu_ops { int (*set_hwmode)(struct iris_core *core); void (*set_preset_registers)(struct iris_core *core); void (*interrupt_init)(struct iris_core *core); + void (*disable_arp)(struct iris_core *core); }; int iris_vpu_boot_firmware(struct iris_core *core); From 6705400386b53fca6a2b3d36fd413260bf86a4be Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:05 +0300 Subject: [PATCH 0196/1058] FROMLIST: media: iris: Add platform data field for watchdog interrupt mask For AR50LT core, the value of WRAPPER_INTR_STATUS_A2HWD_BMASK differs from the currently supported VPUs. In preparation for adding AR50LT support in subsequent patches, introduce a platform data field, wd_intr_mask, to capture the watchdog interrupt bitmask per platform. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-6-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_platform_common.h | 1 + drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 4 ++++ drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 6 ++++++ drivers/media/platform/qcom/iris/iris_vpu_common.c | 8 +++++--- .../media/platform/qcom/iris/iris_vpu_register_defines.h | 1 - 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 55a4fa3569852..81fcb2854772d 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -315,6 +315,7 @@ struct iris_platform_data { u32 tz_cp_config_data_size; u32 num_vpp_pipe; bool no_aon; + u32 wd_intr_mask; u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index 961dce2e6aa92..eeef453c583f2 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -16,6 +16,8 @@ #include "iris_platform_sc7280.h" #include "iris_platform_sm8250.h" +#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) + static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = { .firmware_data = &iris_hfi_gen1_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -94,6 +96,7 @@ const struct iris_platform_data sc7280_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2), .num_vpp_pipe = 1, .no_aon = true, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256, /* max spec for SC7280 is 4096x2176@60fps */ @@ -124,6 +127,7 @@ const struct iris_platform_data sm8250_data = { .tz_cp_config_data = tz_cp_config_vpu2, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, .max_core_mbps = ((7680 * 4320) / 256) * 60, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 74626b35d9cb3..261db38a013b3 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -18,6 +18,8 @@ #include "iris_platform_sm8750.h" #include "iris_platform_x1p42100.h" +#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) + static const struct iris_firmware_desc iris_vpu30_p4_s6_gen2_desc = { .firmware_data = &iris_hfi_gen2_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -113,6 +115,7 @@ const struct iris_platform_data qcs8300_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 2, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, .max_core_mbps = (((3840 * 2176) / 256) * 120), @@ -142,6 +145,7 @@ const struct iris_platform_data sm8550_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -179,6 +183,7 @@ const struct iris_platform_data sm8650_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -208,6 +213,7 @@ const struct iris_platform_data sm8750_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 375bcd9234766..41498f94480e8 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -109,11 +109,11 @@ void iris_vpu_raise_interrupt(struct iris_core *core) void iris_vpu_clear_interrupt(struct iris_core *core) { + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask; u32 intr_status, mask; intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS); - mask = (WRAPPER_INTR_STATUS_A2H_BMSK | - WRAPPER_INTR_STATUS_A2HWD_BMSK | + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | wd_intr_mask | CTRL_INIT_IDLE_MSG_BMSK); if (intr_status & mask) @@ -124,7 +124,9 @@ void iris_vpu_clear_interrupt(struct iris_core *core) int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) { - if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) { + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask; + + if (intr_status & wd_intr_mask) { dev_err(core->dev, "received watchdog interrupt\n"); return -ETIME; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 72168b9ffa738..4fffa094c52fe 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -41,7 +41,6 @@ #define MSK_CORE_POWER_ON BIT(1) #define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) -#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) #define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) #define WRAPPER_INTR_MASK (WRAPPER_BASE_OFFS + 0x10) From 476f19f4faf6b3618622d0f0a5df19026274406b Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:06 +0300 Subject: [PATCH 0197/1058] FROMLIST: media: iris: Add platform flag for instantaneous bandwidth voting AR50LT require explicit instantaneous bandwidth (IB) voting in addition to average bandwidth (AB) when configuring interconnect QoS. This requirement is due to QSB (Qualcomm System Bus) 128b to QNS ( Qualcomm Network Switch) 256b conversion at video noc in AR50LT which is not needed for other IRIS cores. In preparation of adding support for AR50LT core, introduce platform-configurable IB multiplier and enable IB voting for all SoCs. Existing platforms default to IB == AB, while AR50LT requires 2x peak bandwidth. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-7-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_platform_common.h | 1 + drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 2 ++ drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 4 ++++ drivers/media/platform/qcom/iris/iris_resources.c | 2 ++ 4 files changed, 9 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 81fcb2854772d..accc1627defda 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -316,6 +316,7 @@ struct iris_platform_data { u32 num_vpp_pipe; bool no_aon; u32 wd_intr_mask; + u32 icc_ib_multiplier; u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index eeef453c583f2..e2fddc29abc72 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -97,6 +97,7 @@ const struct iris_platform_data sc7280_data = { .num_vpp_pipe = 1, .no_aon = true, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256, /* max spec for SC7280 is 4096x2176@60fps */ @@ -128,6 +129,7 @@ const struct iris_platform_data sm8250_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2), .num_vpp_pipe = 4, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, .max_core_mbps = ((7680 * 4320) / 256) * 60, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 261db38a013b3..64cf182d67ccd 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -116,6 +116,7 @@ const struct iris_platform_data qcs8300_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 2, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, .max_core_mbps = (((3840 * 2176) / 256) * 120), @@ -146,6 +147,7 @@ const struct iris_platform_data sm8550_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -184,6 +186,7 @@ const struct iris_platform_data sm8650_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -214,6 +217,7 @@ const struct iris_platform_data sm8750_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 773f6548370a2..caeaf199cef74 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -18,6 +18,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw) { + u32 icc_ib_multiplier = core->iris_platform_data->icc_ib_multiplier; unsigned long bw_kbps = 0, bw_prev = 0; const struct icc_info *icc_tbl; int ret = 0, i; @@ -36,6 +37,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw) return ret; core->icc_tbl[i].avg_bw = bw_kbps; + core->icc_tbl[i].peak_bw = bw_kbps * icc_ib_multiplier; core->power.icc_bw = bw_kbps; break; From ac939cb3b551372de2c063c5d86f655c73b212e9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:07 +0300 Subject: [PATCH 0198/1058] FROMLIST: media: iris: skip PIPE if it is not supported by the platform AR50Lt doesn't support HFI_PROPERTY_PARAM_WORK_ROUTE. Tables for AR50LT won't have corresponding entry in the capability tables. Let iris_set_pipe() silently skip propgramming the property if there is no corresponding capability. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-8-df3846e74347@oss.qualcomm.com/ Reviewed-by: Vishnu Reddy Reviewed-by: Vikash Garodia Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_ctrls.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 10e33b8a73f60..33a34573391a4 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -534,6 +534,9 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) u32 work_route = inst->fw_caps[PIPE].value; u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + if (!hfi_id) + return 0; + return hfi_ops->session_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, iris_get_port_info(inst, cap_id), From 3e378a18275fcd66b2c5e71c497f0143bec3ea2a Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:08 +0300 Subject: [PATCH 0199/1058] FROMLIST: media: iris: Add framework support for AR50_LITE video core Add power sequence for ar5lt core. Add register handling for ar50lt by hooking up vpu op with ar50lt specific implemtation or resue from earlier generation wherever feasible. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-9-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/Makefile | 1 + .../platform/qcom/iris/iris_platform_common.h | 2 + .../platform/qcom/iris/iris_vpu_ar50lt.c | 156 ++++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.c | 3 +- .../platform/qcom/iris/iris_vpu_common.h | 1 + 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 48e415cbc4390..f1b204b95694e 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -26,6 +26,7 @@ qcom-iris-objs += iris_buffer.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu4x.o \ + iris_vpu_ar50lt.o \ iris_vpu_buffer.o \ iris_vpu_common.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index accc1627defda..6a189489369f0 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -74,6 +74,7 @@ enum platform_clk_type { IRIS_VPP0_HW_CLK, IRIS_VPP1_HW_CLK, IRIS_APV_HW_CLK, + IRIS_THROTTLE_CLK, }; struct platform_clk_data { @@ -315,6 +316,7 @@ struct iris_platform_data { u32 tz_cp_config_data_size; u32 num_vpp_pipe; bool no_aon; + bool no_rpmh; u32 wd_intr_mask; u32 icc_ib_multiplier; u32 max_session_count; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c new file mode 100644 index 0000000000000..1af20b067c032 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include + +#include "iris_instance.h" +#include "iris_vpu_common.h" + +#include "iris_vpu_register_defines.h" + +#define WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT BIT(3) + +#define WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT 0xb0080 + +#define CPU_CS_VCICMD 0xa0020 +#define CPU_CS_VCICMD_ARP_OFF 0x1 + +static void iris_vpu_ar50lt_set_preset_registers(struct iris_core *core) +{ + writel(0x0, core->reg_base + WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT); +} + +static void iris_vpu_ar50lt_interrupt_init(struct iris_core *core) +{ + writel(WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT, core->reg_base + WRAPPER_INTR_MASK); +} + +static void iris_vpu_ar50lt_disable_arp(struct iris_core *core) +{ + writel(CPU_CS_VCICMD_ARP_OFF, core->reg_base + CPU_CS_VCICMD); +} + +static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) +{ + iris_disable_unprepare_clock(core, IRIS_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + return 0; +} + +static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core) +{ + dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); + iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK); + iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); +} + +static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + if (ret && ret != -ENOENT) + goto err_disable_ctrl_clock; + + ret = iris_prepare_enable_clock(core, IRIS_AHB_CLK); + if (ret) + goto err_disable_axi_clock; + + return 0; + +err_disable_axi_clock: + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); +err_disable_ctrl_clock: + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + return ret; +} + +static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); + if (ret) + goto err_disable_hw_clock; + + ret = iris_prepare_enable_clock(core, IRIS_THROTTLE_CLK); + if (ret) + goto err_disable_hw_ahb_clock; + + return 0; + +err_disable_hw_ahb_clock: + iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); +err_disable_hw_clock: + iris_disable_unprepare_clock(core, IRIS_HW_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + + return ret; +} + +static u64 iris_vpu_ar50lt_calc_freq(struct iris_inst *inst, size_t data_size) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct v4l2_format *inp_f = inst->fmt_src; + u32 mbs_per_second, mbpf, height, width; + unsigned long vpp_freq, vsp_freq; + u32 fps = DEFAULT_FPS; + + width = max(inp_f->fmt.pix_mp.width, inst->crop.width); + height = max(inp_f->fmt.pix_mp.height, inst->crop.height); + + mbpf = NUM_MBS_PER_FRAME(height, width); + mbs_per_second = mbpf * fps; + + vpp_freq = mbs_per_second * caps->mb_cycles_vpp; + + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_second * caps->mb_cycles_vsp; + + /* 10 / 7 is overhead factor */ + vsp_freq += ((fps * data_size * 8) * 10) / 7; + + return max(vpp_freq, vsp_freq); +} + +const struct vpu_ops iris_vpu_ar50lt_ops = { + .power_off_hw = iris_vpu_ar50lt_power_off_hw, + .power_on_hw = iris_vpu_ar50lt_power_on_hw, + .power_off_controller = iris_vpu_ar50lt_power_off_controller, + .power_on_controller = iris_vpu_ar50lt_power_on_controller, + .calc_freq = iris_vpu_ar50lt_calc_freq, + .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_ar50lt_set_preset_registers, + .interrupt_init = iris_vpu_ar50lt_interrupt_init, + .disable_arp = iris_vpu_ar50lt_disable_arp, +}; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 41498f94480e8..75dc051cc6cbc 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -97,7 +97,8 @@ int iris_vpu_boot_firmware(struct iris_core *core) } writel(HOST2XTENSA_INTR_ENABLE, core->reg_base + CPU_CS_H2XSOFTINTEN); - writel(0x0, core->reg_base + CPU_CS_X2RPMH); + if (!core->iris_platform_data->no_rpmh) + writel(0x0, core->reg_base + CPU_CS_X2RPMH); return 0; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 71d96921ed372..f00e2de5fa537 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -13,6 +13,7 @@ extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; extern const struct vpu_ops iris_vpu35_ops; extern const struct vpu_ops iris_vpu4x_ops; +extern const struct vpu_ops iris_vpu_ar50lt_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); From f9c9295dd8915e6ebee971d101df8c210db68328 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:09 +0300 Subject: [PATCH 0200/1058] FROMLIST: media: iris: add minimal GET_PROPERTY implementation AR50Lt with the Gen1 firmware requires host to read HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS property, otherwie it doesn't update internal data and fails the HFI_CMD_SESSION_LOAD_RESOURCES command. Implement minimal support for querying the properties from the firmware. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-10-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dmitry Baryshkov --- .../platform/qcom/iris/iris_hfi_common.h | 1 + .../qcom/iris/iris_hfi_gen1_command.c | 21 +++++++++++++++++++ .../qcom/iris/iris_hfi_gen1_defines.h | 15 +++++++++++++ .../qcom/iris/iris_hfi_gen1_response.c | 6 ++++++ 4 files changed, 43 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index a27447eb25199..16099f9a25b65 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -121,6 +121,7 @@ struct iris_hfi_session_ops { int (*session_set_property)(struct iris_inst *inst, u32 packet_type, u32 flag, u32 plane, u32 payload_type, void *payload, u32 payload_size); + int (*session_get_property)(struct iris_inst *inst, u32 packet_type); int (*session_open)(struct iris_inst *inst); int (*session_start)(struct iris_inst *inst, u32 plane); int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 7674b47ad6c49..99e82e5510abe 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -1117,10 +1117,31 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p return 0; } +static int iris_hfi_gen1_session_get_property(struct iris_inst *inst, u32 packet_type) +{ + struct hfi_session_get_property_pkt pkt; + int ret; + + pkt.shdr.hdr.size = sizeof(pkt); + pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_GET_PROPERTY; + pkt.shdr.session_id = inst->session_id; + pkt.num_properties = 1; + pkt.data = packet_type; + + reinit_completion(&inst->completion); + + ret = iris_hfi_queue_cmd_write(inst->core, &pkt, pkt.shdr.hdr.size); + if (ret) + return ret; + + return iris_wait_for_session_response(inst, false); +} + static const struct iris_hfi_session_ops iris_hfi_gen1_session_ops = { .session_open = iris_hfi_gen1_session_open, .session_set_config_params = iris_hfi_gen1_session_set_config_params, .session_set_property = iris_hfi_gen1_session_set_property, + .session_get_property = iris_hfi_gen1_session_get_property, .session_start = iris_hfi_gen1_session_start, .session_queue_buf = iris_hfi_gen1_session_queue_buffer, .session_release_buf = iris_hfi_gen1_session_unset_buffers, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 0e4dee1923846..bb495a1d2623e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -35,6 +35,7 @@ #define HFI_CMD_SESSION_EMPTY_BUFFER 0x211004 #define HFI_CMD_SESSION_FILL_BUFFER 0x211005 #define HFI_CMD_SESSION_FLUSH 0x211008 +#define HFI_CMD_SESSION_GET_PROPERTY 0x211009 #define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c #define HFI_CMD_SESSION_CONTINUE 0x21100d @@ -113,6 +114,7 @@ #define HFI_MSG_SESSION_FLUSH 0x221006 #define HFI_MSG_SESSION_EMPTY_BUFFER 0x221007 #define HFI_MSG_SESSION_FILL_BUFFER 0x221008 +#define HFI_MSG_SESSION_PROPERTY_INFO 0x221009 #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a #define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c @@ -205,6 +207,12 @@ struct hfi_session_set_property_pkt { u32 data[]; }; +struct hfi_session_get_property_pkt { + struct hfi_session_hdr_pkt shdr; + u32 num_properties; + u32 data; +}; + struct hfi_sys_pc_prep_pkt { struct hfi_pkt_hdr hdr; }; @@ -574,6 +582,13 @@ struct hfi_msg_session_fbd_uncompressed_plane0_pkt { u32 data[]; }; +struct hfi_msg_session_property_info_pkt { + struct hfi_session_hdr_pkt shdr; + u32 num_properties; + u32 property; + u8 data[]; +}; + struct hfi_msg_session_release_buffers_done_pkt { struct hfi_msg_session_hdr_pkt shdr; u32 num_buffers; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index bfd7495bf44f0..23fc7194b1e3a 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -591,6 +591,10 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { .pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), }, + { + .pkt = HFI_MSG_SESSION_PROPERTY_INFO, + .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), + }, }; static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) @@ -652,6 +656,8 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response iris_hfi_gen1_session_etb_done(inst, hdr); } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) { iris_hfi_gen1_session_ftb_done(inst, hdr); + } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) { + complete(&inst->completion); } else { struct hfi_msg_session_hdr_pkt *shdr; From 4ec08f95016b1e030374685254c38c7f5190e3ce Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:10 +0300 Subject: [PATCH 0201/1058] FROMLIST: media: iris: update buffer requirements based on received info Upon receiving data for HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS the driver should update buffer sizes and counts from the received data. Implement corresponding functionality updating buffers data. This will be used for upcoming support of AR50Lt platforms with Gen1 firmware. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-11-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dmitry Baryshkov --- .../qcom/iris/iris_hfi_gen1_response.c | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 23fc7194b1e3a..ee996eb1f41fa 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -533,6 +533,78 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) dev_err(core->dev, "error in ftb done\n"); } +static enum iris_buffer_type iris_hfi_gen1_buf_type(struct iris_inst *inst, u32 type) +{ + switch (type) { + case HFI_BUFFER_INPUT: + return BUF_INPUT; + case HFI_BUFFER_OUTPUT: + if (iris_split_mode_enabled(inst)) + return BUF_DPB; + return BUF_OUTPUT; + case HFI_BUFFER_OUTPUT2: + if (iris_split_mode_enabled(inst)) + return BUF_OUTPUT; + return BUF_DPB; + case HFI_BUFFER_INTERNAL_PERSIST_1: + return BUF_PERSIST; + case HFI_BUFFER_INTERNAL_SCRATCH: + return BUF_BIN; + case HFI_BUFFER_INTERNAL_SCRATCH_1: + return BUF_SCRATCH_1; + case HFI_BUFFER_INTERNAL_SCRATCH_2: + return BUF_SCRATCH_2; + case HFI_BUFFER_INTERNAL_PERSIST: + return BUF_ARP; + default: + return -EINVAL; + } +} + +static void iris_hfi_gen1_session_buffer_requirements(struct iris_inst *inst, + void *data, size_t size) +{ + struct hfi_buffer_requirements *req; + + if (!size || size % sizeof(*req)) + return; + + for (req = data; size; size -= sizeof(*req), req++) { + enum iris_buffer_type type = iris_hfi_gen1_buf_type(inst, req->type); + + if (type == -EINVAL) + continue; + + inst->buffers[type].min_count = req->hold_count; + inst->buffers[type].size = req->size; + + if (type == BUF_OUTPUT) + inst->fw_min_count = req->count_actual; + } +} + +static void iris_hfi_gen1_session_property_info(struct iris_inst *inst, void *packet) +{ + struct hfi_msg_session_property_info_pkt *pkt = packet; + + if (!pkt->num_properties) { + dev_err(inst->core->dev, "error, no properties\n"); + goto out; + } + + switch (pkt->property) { + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + iris_hfi_gen1_session_buffer_requirements(inst, pkt->data, + pkt->shdr.hdr.size - sizeof(*pkt)); + break; + default: + dev_warn(inst->core->dev, "unknown property id: %x\n", pkt->property); + } + +out: + complete(&inst->completion); +} + struct iris_hfi_gen1_response_pkt_info { u32 pkt; u32 pkt_sz; @@ -657,7 +729,7 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) { iris_hfi_gen1_session_ftb_done(inst, hdr); } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) { - complete(&inst->completion); + iris_hfi_gen1_session_property_info(inst, hdr); } else { struct hfi_msg_session_hdr_pkt *shdr; From 74b9e1507fffce7b1d3e1474a6d4e6db8fc527a9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:11 +0300 Subject: [PATCH 0202/1058] FROMLIST: media: iris: implement support for the Agatti platform Port support for the AR50Lt video codec core (present for example on the Agatti platform) to the Iris driver. Unlike more recent cores this generation doesn't have the PIPE property (as it always has only one pipe). Also, unlike newer platforms, buffer sizes are requested from the firmware instead of being calculated by the driver. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-12-df3846e74347@oss.qualcomm.com/ Co-developed-by: Dikshita Agarwal Signed-off-by: Dikshita Agarwal Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/Makefile | 1 + .../media/platform/qcom/iris/iris_hfi_gen1.c | 227 ++++++++++++++++++ .../platform/qcom/iris/iris_platform_common.h | 5 + .../qcom/iris/iris_platform_vpu_ar50lt.c | 110 +++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 + .../platform/qcom/iris/iris_vpu_buffer.c | 13 + .../platform/qcom/iris/iris_vpu_buffer.h | 1 + 7 files changed, 361 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index f1b204b95694e..bbd1f724963e6 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -14,6 +14,7 @@ qcom-iris-objs += iris_buffer.o \ iris_hfi_queue.o \ iris_platform_vpu2.o \ iris_platform_vpu3x.o \ + iris_platform_vpu_ar50lt.o \ iris_power.o \ iris_probe.o \ iris_resources.o \ diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c index ca1545d28b531..f57af31dbd9f0 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c @@ -443,3 +443,230 @@ const struct iris_firmware_data iris_hfi_gen1_data = { .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), }; + +static const struct platform_inst_fw_cap iris_inst_fw_cap_gen1_ar50lt_dec[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, +}; + +static const struct platform_inst_fw_cap inst_fw_cap_gen1_ar50lt_enc[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen1, + }, + { + .cap_id = BITRATE, + .min = BITRATE_MIN, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = BITRATE_STEP, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate_gen1, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen1, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = (1 << 16) - 1, + .step_or_mask = 1, + .value = 30, + .set = iris_set_u32 + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen1, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MAX_QP_HEVC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, +}; + +static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_SCRATCH_1, +}; + +const struct iris_firmware_data iris_hfi_gen1_ar50lt_data = { + .init_hfi_ops = &iris_hfi_gen1_sys_ops_init, + + .inst_fw_caps_dec = iris_inst_fw_cap_gen1_ar50lt_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(iris_inst_fw_cap_gen1_ar50lt_dec), + .inst_fw_caps_enc = inst_fw_cap_gen1_ar50lt_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen1_ar50lt_enc), + + .dec_input_config_params_default = + sm8250_vdec_input_config_param_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8250_vdec_input_config_param_default), + .enc_input_config_params = sm8250_venc_input_config_param, + .enc_input_config_params_size = + ARRAY_SIZE(sm8250_venc_input_config_param), + + .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl), + + .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 6a189489369f0..d1cf596ca349a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -38,6 +38,9 @@ struct iris_inst; #define MAX_HEVC_LAYER_HP_SLIDING_WINDOW 3 #define MAX_HEVC_VBR_LAYER_HP_SLIDING_WINDOW 5 #define MAX_HIER_CODING_LAYER_GEN1 6 +#define BITRATE_MAX_AR50LT 100000000 +#define BITRATE_DEFAULT_AR50LT 20000000 +#define MIN_QP_8BIT_AR50LT 0 enum stage_type { STAGE_1 = 1, @@ -51,8 +54,10 @@ enum pipe_type { }; extern const struct iris_firmware_data iris_hfi_gen1_data; +extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data; extern const struct iris_firmware_data iris_hfi_gen2_data; +extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; extern const struct iris_platform_data sc7280_data; extern const struct iris_platform_data sm8250_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c new file mode 100644 index 0000000000000..393256f39112b --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_ctrls.h" +#include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_defines.h" +#include "iris_platform_common.h" +#include "iris_vpu_buffer.h" +#include "iris_vpu_common.h" + +#define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10 + +const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_s6_desc = { + .firmware_data = &iris_hfi_gen1_ar50lt_data, + .get_vpu_buffer_size = iris_vpu_ar50lt_gen1_buf_size, + .fwname = "qcom/venus-6.0/venus.mbn", +}; + +static const u32 iris_fmts_ar50lt_dec[] = { + [IRIS_FMT_H264] = V4L2_PIX_FMT_H264, + [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC, + [IRIS_FMT_VP9] = V4L2_PIX_FMT_VP9, +}; + +static const struct bw_info iris_bw_table_dec_ar50lt[] = { + { ((1920 * 1080) / 256) * 60, 1564000, }, + { ((1920 * 1080) / 256) * 30, 791000, }, + { ((1280 * 720) / 256) * 60, 688000, }, + { ((1280 * 720) / 256) * 30, 347000, }, +}; + +static const struct icc_info iris_icc_info_ar50lt[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 6500000 }, +}; + +static const char * const iris_pmdomain_table_ar50lt[] = { "venus", "vcodec0" }; + +static const char * const iris_opp_pd_table_ar50lt[] = { "cx" }; + +static const struct platform_clk_data iris_clk_table_ar50lt[] = { + {IRIS_CTRL_CLK, "core" }, + {IRIS_AXI_CLK, "iface" }, + {IRIS_AHB_CLK, "bus" }, + {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_HW_AHB_CLK, "vcodec0_bus" }, + {IRIS_THROTTLE_CLK, "throttle" }, +}; + +static const char * const iris_opp_clk_table_ar50lt[] = { + "vcodec0_core", + NULL, +}; + +static const struct tz_cp_config tz_cp_config_ar50lt[] = { + { + .cp_start = 0, + .cp_size = 0x25800000, + .cp_nonpixel_start = 0x01000000, + .cp_nonpixel_size = 0x24800000, + }, +}; + +static struct platform_inst_caps platform_inst_cap_ar50lt = { + .min_frame_width = 128, + .max_frame_width = 1920, + .min_frame_height = 128, + .max_frame_height = 1920, + .max_mbpf = (1920 * 1088) / 256, + .mb_cycles_vpp = 440, + .mb_cycles_fw = 733003, + .mb_cycles_fw_vpp = 225975, + .max_frame_rate = 120, + .max_operating_rate = 120, +}; + +const struct iris_platform_data qcm2290_data = { + .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_s6_desc, + .vpu_ops = &iris_vpu_ar50lt_ops, + .icc_tbl = iris_icc_info_ar50lt, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt), + .bw_tbl_dec = iris_bw_table_dec_ar50lt, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_ar50lt), + .pmdomain_tbl = iris_pmdomain_table_ar50lt, + .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_ar50lt), + .opp_pd_tbl = iris_opp_pd_table_ar50lt, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_ar50lt), + .clk_tbl = iris_clk_table_ar50lt, + .clk_tbl_size = ARRAY_SIZE(iris_clk_table_ar50lt), + .opp_clk_tbl = iris_opp_clk_table_ar50lt, + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .inst_iris_fmts = iris_fmts_ar50lt_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_ar50lt_dec), + .inst_caps = &platform_inst_cap_ar50lt, + .tz_cp_config_data = tz_cp_config_ar50lt, + .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_ar50lt), + .num_vpp_pipe = 1, + .no_rpmh = true, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 2, + .max_session_count = 8, + .max_core_mbpf = ((1920 * 1088) / 256) * 4, + /* Concurrency: 1080p@30 decode + 1080p@30 encode */ + /* Concurrency: 3 * 1080p@30 decode */ + .max_core_mbps = (((1920 * 1088) / 256) * 90), +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 7fe31136df21b..472d9e293ece0 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -356,6 +356,10 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,qcm2290-venus", + .data = &qcm2290_data, + }, { .compatible = "qcom,qcs8300-iris", .data = &qcs8300_data, diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index fb6f1016415e2..4a39b8fef52b0 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2194,6 +2194,19 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ return size; } +u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; + int ret; + + /* return 0 on error to let the driver cope */ + ret = hfi_ops->session_get_property(inst, HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS); + if (ret) + return 0; + + return inst->buffers[buffer_type].size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 8c0d6b7b5de85..1d07137c70cd7 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -288,6 +288,7 @@ static inline u32 size_av1d_qp(u32 frame_width, u32 frame_height) u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif From 936dbb16bbde24c1fac59c7107f8f95d8e1a6287 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:12 +0300 Subject: [PATCH 0203/1058] FROMLIST: media: iris: Introduce buffer size calculations for AR50LT Introduces AR50LT buffer size calculation for both encoder and decoder. Reuse the buffer size calculation which are common, while adding the AR50LT specific ones separately. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-13-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Signed-off-by: Dmitry Baryshkov --- .../platform/qcom/iris/iris_vpu_buffer.c | 401 ++++++++++++++++++ .../platform/qcom/iris/iris_vpu_buffer.h | 37 ++ 2 files changed, 438 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 4a39b8fef52b0..ca03d65705136 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -50,6 +50,32 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); } +static u32 size_h264d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = ((frame_width * frame_height * 3) >> 1); + if (size_yuv <= 1920 * 1088 * 3 / 2) { + size_bin_hdr = size_yuv * H264_CABAC_HDR_RATIO_SM_TOT; + size_bin_res = size_yuv * H264_CABAC_RES_RATIO_SM_TOT; + } else { + size_bin_hdr = (size_yuv * 3) / 5; + size_bin_res = (size_yuv * 3) / 2; + } + size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT); + size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT); + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_h = ALIGN(frame_height, 16); + u32 n_aligned_w = ALIGN(frame_width, 16); + + return size_h264d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + static u32 size_av1d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 size_yuv, size_bin_hdr, size_bin_res; @@ -103,6 +129,21 @@ static u32 hfi_buffer_bin_vp9d(u32 frame_width, u32 frame_height, u32 num_vpp_pi return _size * num_vpp_pipes; } +static u32 hfi_buffer_bin_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size; + + size_yuv = ALIGN(frame_width, 16) * ALIGN(frame_height, 16) * 3 / 2; + size_yuv = ALIGN(size_yuv, DMA_ALIGNMENT); + + size = ALIGN(((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 6) / 5) / + num_vpp_pipes), DMA_ALIGNMENT) + + ALIGN((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 4) / num_vpp_pipes), + DMA_ALIGNMENT); + + return size * num_vpp_pipes; +} + static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 n_aligned_w = ALIGN(frame_width, 16); @@ -111,6 +152,32 @@ static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_p return size_h265d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); } +static u32 size_h265d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = ((frame_width * frame_height * 3) >> 1); + if (size_yuv <= ((BIN_BUFFER_THRESHOLD * 3) >> 1)) { + size_bin_hdr = size_yuv * H265_CABAC_HDR_RATIO_SM_TOT; + size_bin_res = size_yuv * H265_CABAC_RES_RATIO_SM_TOT; + } else { + size_bin_hdr = (size_yuv * 41) / 50; + size_bin_res = (size_yuv * 59) / 50; + } + size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT); + size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT); + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_w = ALIGN(frame_width, 16); + u32 n_aligned_h = ALIGN(frame_height, 16); + + return size_h265d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) { u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16); @@ -174,6 +241,14 @@ static u32 size_h264d_bse_cmd_buf(u32 frame_height) SIZE_H264D_BSE_CMD_PER_BUF; } +static u32 size_h264d_bse_cmd_buf_ar50lt(u32 frame_height) +{ + u32 height = ALIGN(frame_height, 32); + + return min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) * + SIZE_H264D_BSE_CMD_PER_BUF; +} + static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height) { u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * @@ -185,6 +260,18 @@ static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height) return _size; } +static u32 size_h265d_bse_cmd_buf_ar50lt(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + + _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1); + _size = 2 * _size * SIZE_H265D_BSE_CMD_PER_BUF; + + return _size; +} + static u32 hfi_buffer_persist_h265d(u32 rpu_enabled) { return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + @@ -195,6 +282,13 @@ static u32 hfi_buffer_persist_h265d(u32 rpu_enabled) DMA_ALIGNMENT); } +static u32 hfi_buffer_persist_h265d_ar50lt(void) +{ + return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + + H265_NUM_TILE * sizeof(u32) + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA), + DMA_ALIGNMENT); +} + static inline u32 hfi_iris3_vp9d_comv_size(void) { @@ -212,6 +306,13 @@ static u32 hfi_buffer_persist_vp9d(void) HDR10_HIST_EXTRADATA_SIZE; } +static u32 hfi_buffer_persist_vp9d_ar50lt(void) +{ + return ALIGN(VP9_NUM_PROBABILITY_TABLE_BUF * VP9_PROB_TABLE_SIZE, DMA_ALIGNMENT) + + ALIGN(hfi_iris3_vp9d_comv_size(), DMA_ALIGNMENT) + + ALIGN(MAX_SUPERFRAME_HEADER_LEN, DMA_ALIGNMENT); +} + static u32 size_h264d_vpp_cmd_buf(u32 frame_height) { u32 size, height = ALIGN(frame_height, 32); @@ -222,6 +323,16 @@ static u32 size_h264d_vpp_cmd_buf(u32 frame_height) return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; } +static u32 size_h264d_vpp_cmd_buf_ar50lt(u32 frame_height) +{ + u32 size, height = ALIGN(frame_height, 32); + + size = min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) * + SIZE_H264D_VPP_CMD_PER_BUF; + + return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; +} + static u32 hfi_buffer_persist_h264d(void) { return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 + @@ -230,6 +341,11 @@ static u32 hfi_buffer_persist_h264d(void) DMA_ALIGNMENT); } +static u32 hfi_buffer_persist_h264d_ar50lt(void) +{ + return ALIGN((SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264), DMA_ALIGNMENT); +} + static u32 hfi_buffer_persist_av1d(u32 max_width, u32 max_height, u32 total_ref_count) { u32 comv_size, size; @@ -255,6 +371,17 @@ static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_ return ALIGN(size, DMA_ALIGNMENT); } +static u32 hfi_buffer_non_comv_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_bse = size_h264d_bse_cmd_buf_ar50lt(frame_height); + u32 size_vpp = size_h264d_vpp_cmd_buf_ar50lt(frame_height); + u32 size = ALIGN(size_bse, DMA_ALIGNMENT) + + ALIGN(size_vpp, DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height) { u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * @@ -269,6 +396,20 @@ static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height) return _size; } +static u32 size_h265d_vpp_cmd_buf_ar50lt(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1); + _size = ALIGN(_size, 4); + _size = 2 * _size * SIZE_H265D_VPP_CMD_PER_BUF_AR50LT; + if (_size > VPP_CMD_MAX_SIZE) + _size = VPP_CMD_MAX_SIZE; + + return _size; +} + static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 _size_bse = size_h265d_bse_cmd_buf(frame_width, frame_height); @@ -285,6 +426,20 @@ static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_ return ALIGN(_size, DMA_ALIGNMENT); } +static u32 hfi_buffer_non_comv_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 _size_bse = size_h265d_bse_cmd_buf_ar50lt(frame_width, frame_height); + u32 _size_vpp = size_h265d_vpp_cmd_buf_ar50lt(frame_width, frame_height); + u32 _size = ALIGN(_size_bse, DMA_ALIGNMENT) + + ALIGN(_size_vpp, DMA_ALIGNMENT) + + ALIGN(2 * sizeof(u16) * + (ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS), DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H265D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(_size, DMA_ALIGNMENT); +} + static u32 size_vpss_lb(u32 frame_width, u32 frame_height) { u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; @@ -317,6 +472,13 @@ u32 size_h265d_lb_fe_top_data(u32 frame_width, u32 frame_height) (ALIGN(frame_width, 64) + 8) * 2; } +static inline +u32 size_h265d_lb_fe_top_data_ar50lt(u32 frame_width, u32 frame_height) +{ + return ALIGN(MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * + (ALIGN(frame_width, 64) + 8), DMA_ALIGNMENT) * 2; +} + static inline u32 size_h265d_lb_fe_top_ctrl(u32 frame_width, u32 frame_height) { @@ -348,6 +510,17 @@ u32 size_h265d_lb_se_left_ctrl(u32 frame_width, u32 frame_height) MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); } +static inline +u32 size_h265d_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 16 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT, + max_t(u32, ((frame_height + 32 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT, + ((frame_height + 64 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT)); +} + static inline u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height) { @@ -355,6 +528,13 @@ u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height) (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS); } +static inline +u32 size_h265d_lb_pe_top_data_ar50lt(u32 frame_width, u32 frame_height) +{ + return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT * + (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS); +} + static inline u32 size_h265d_lb_vsp_top(u32 frame_width, u32 frame_height) { @@ -404,6 +584,29 @@ u32 hfi_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, u32 nu return ALIGN((_size + vpss_lb_size), DMA_ALIGNMENT); } +static inline +u32 hfi_buffer_line_h265d_ar50lt(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) +{ + u32 size; + + size = ALIGN(size_h265d_lb_fe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_left_ctrl(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_left_ctrl_ar50lt(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_pe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_left(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_recon_dma_metadata_wr(frame_width, frame_height), + DMA_ALIGNMENT) * 4 + + ALIGN(size_h265d_qp(frame_width, frame_height), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static inline u32 size_vpxd_lb_fe_left_ctrl(u32 frame_width, u32 frame_height) { @@ -438,6 +641,17 @@ u32 size_vpxd_lb_se_left_ctrl(u32 frame_width, u32 frame_height) MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); } +static inline +u32 size_vpxd_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 15) >> 4) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT, + max_t(u32, ((frame_height + 31) >> 5) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT, + ((frame_height + 63) >> 6) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT)); +} + static inline u32 size_vpxd_lb_recon_dma_metadata_wr(u32 frame_width, u32 frame_height) { @@ -492,6 +706,19 @@ u32 hfi_iris3_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) ALIGN(size_vp9d_qp(frame_width, frame_height), DMA_ALIGNMENT); } +static inline +u32 hfi_ar50lt_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vpxd_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vp9d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vpxd_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_pe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_fe_top_data(frame_width, frame_height), DMA_ALIGNMENT); +} + static inline u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, bool is_opb, u32 num_vpp_pipes) @@ -507,6 +734,13 @@ u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_mi return _lb_size + vpss_lb_size + 4096; } +static inline +u32 hfi_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, + bool is_opb, u32 num_vpp_pipes) +{ + return hfi_ar50lt_vp9d_lb_size(frame_width, frame_height, num_vpp_pipes); +} + static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) { @@ -529,6 +763,25 @@ static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT); } +static u32 hfi_buffer_line_h264d_ar50lt(u32 frame_width, u32 frame_height, + bool is_opb, u32 num_vpp_pipes) +{ + u32 size; + + size = ALIGN(size_h264d_lb_fe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h264d_lb_se_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_se_left_ctrl_ar50lt(frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_h264d_lb_pe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 + + ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static u32 size_av1d_lb_opb_wr1_nv12_ubwc(u32 frame_width, u32 frame_height) { u32 size, y_width, y_width_a = 128; @@ -724,6 +977,23 @@ static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_bin_h264d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_bin_h265d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_bin_vp9d_ar50lt(width, height, num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) { u32 num_comv = VIDEO_MAX_FRAME; @@ -785,6 +1055,18 @@ static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_persist_size(struct iris_inst *inst) +{ + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_persist_h264d_ar50lt(); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_persist_h265d_ar50lt(); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_persist_vp9d_ar50lt(); + + return 0; +} + static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) @@ -808,6 +1090,21 @@ static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_non_comv_h264d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_non_comv_h265d_ar50lt(width, height, num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_line_size(struct iris_inst *inst) { u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; @@ -833,6 +1130,29 @@ static u32 iris_vpu_dec_line_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + bool is_opb = false; + u32 out_min_count = inst->buffers[BUF_OUTPUT].min_count; + + if (iris_split_mode_enabled(inst)) + is_opb = true; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_line_h264d_ar50lt(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_line_h265d_ar50lt(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_line_vp9d_ar50lt(width, height, out_min_count, is_opb, + num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) { return iris_vpu_dec_comv_size(inst) + @@ -840,6 +1160,13 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) iris_vpu_dec_line_size(inst); } +static u32 iris_vpu_ar50lt_dec_scratch1_size(struct iris_inst *inst) +{ + return iris_vpu_dec_comv_size(inst) + + iris_vpu_ar50lt_dec_non_comv_size(inst) + + iris_vpu_ar50lt_dec_line_size(inst); +} + static inline u32 iris_vpu_enc_get_bitstream_width(struct iris_inst *inst) { if (is_rotation_90_or_270(inst)) @@ -1470,6 +1797,15 @@ u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit) return size; } +static inline +u32 hfi_buffer_dpb_enc_ar50lt(u32 frame_width, u32 frame_height, bool is_ten_bit) +{ + if (!is_ten_bit) + return size_enc_ref_buffer(frame_width, frame_height); + else + return size_enc_ten_bit_ref_buffer(frame_width, frame_height); +} + static u32 iris_vpu_enc_arp_size(struct iris_inst *inst) { return HFI_BUFFER_ARP_ENC; @@ -1494,6 +1830,16 @@ u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable, return 0; } +static inline +u32 hfi_buffer_vpss_enc_ar50lt(u32 dswidth, u32 dsheight, bool ds_enable, + u32 blur, bool is_ten_bit) +{ + if (ds_enable || blur) + return hfi_buffer_dpb_enc_ar50lt(dswidth, dsheight, is_ten_bit); + + return 0; +} + static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height, u32 lcu_size, u32 num_ref, bool ten_bit, u32 num_vpp_pipes, @@ -1752,6 +2098,16 @@ static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst) return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0); } +static u32 iris_vpu_ar50lt_enc_vpss_size(struct iris_inst *inst) +{ + u32 ds_enable = is_scaling_enabled(inst); + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_vpss_enc_ar50lt(width, height, ds_enable, 0, 0); +} + static inline u32 size_dpb_opb(u32 height, u32 lcu_size) { u32 max_tile_height = ((height + lcu_size - 1) / lcu_size) * lcu_size + 8; @@ -2207,6 +2563,51 @@ u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type return inst->buffers[buffer_type].size; } +u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; + u32 size = 0, buf_type_handle_size = 0, i; + + static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_ar50lt_dec_bin_size }, + {BUF_COMV, iris_vpu_dec_comv_size }, + {BUF_NON_COMV, iris_vpu_ar50lt_dec_non_comv_size }, + {BUF_LINE, iris_vpu_ar50lt_dec_line_size }, + {BUF_PERSIST, iris_vpu_ar50lt_dec_persist_size }, + {BUF_DPB, iris_vpu_dec_dpb_size }, + {BUF_SCRATCH_1, iris_vpu_ar50lt_dec_scratch1_size }, + {BUF_PARTIAL, iris_vpu_dec_partial_size }, + }; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_ar50lt_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) { + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + } else if (inst->domain == ENCODER) { + buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr = enc_internal_buf_type_handle; + } + + for (i = 0; i < buf_type_handle_size; i++) { + if (buf_type_handle_arr[i].type == buffer_type) { + size = buf_type_handle_arr[i].handle(inst); + break; + } + } + + return size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 1d07137c70cd7..2085e316a6bd8 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -61,17 +61,26 @@ struct iris_inst; #define MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE 64 #define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE (128 / 8) #define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE (128 / 8) +#define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT (8 / 8) +#define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT (16 / 8) +#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT (32 / 8) #define VP9_UDC_HEADER_BUF_SIZE (3 * 128) #define SIZE_SEI_USERDATA 4096 #define SIZE_DOLBY_RPU_METADATA (41 * 1024) #define H264_CABAC_HDR_RATIO_HD_TOT 1 #define H264_CABAC_RES_RATIO_HD_TOT 3 +#define H264_CABAC_HDR_RATIO_SM_TOT 1 +#define H264_CABAC_RES_RATIO_SM_TOT 2 #define H265D_MAX_SLICE 3600 +#define H265D_MAX_SLICE_AR50LT 600 #define SIZE_H265D_HW_PIC_T SIZE_H264D_HW_PIC_T #define H265_CABAC_HDR_RATIO_HD_TOT 2 #define H265_CABAC_RES_RATIO_HD_TOT 2 +#define H265_CABAC_HDR_RATIO_SM_TOT 1 +#define H265_CABAC_RES_RATIO_SM_TOT 6 #define SIZE_H265D_VPP_CMD_PER_BUF (256) +#define SIZE_H265D_VPP_CMD_PER_BUF_AR50LT (192) #define SIZE_THREE_DIMENSION_USERDATA 768 #define SIZE_H265D_ARP 9728 @@ -81,6 +90,7 @@ struct iris_inst; #define VPX_DECODER_FRAME_BIN_DENOMINATOR 2 #define VPX_DECODER_FRAME_BIN_RES_BUDGET_RATIO (3 / 2) +#define VPX_DECODER_FRAME_BIN_BUFFER_SIZE (1024 * 1024) #define SIZE_H264D_HW_PIC_T (BIT(11)) @@ -99,6 +109,7 @@ struct iris_inst; #define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 #define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16 #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 +#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT 176 #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 #define AV1_CABAC_HDR_RATIO_HD_TOT 2 @@ -155,11 +166,21 @@ static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; } +static inline u32 size_h264d_lb_fe_top_data_ar50lt(u32 frame_width) +{ + return 16 * ALIGN(frame_width, 16) * 2; +} + static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width) { return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_fe_top_ctrl_ar50lt(u32 frame_width) +{ + return 16 * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height) { return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); @@ -170,16 +191,31 @@ static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width) return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_se_top_ctrl_ar50lt(u32 frame_width) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height) { return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); } +static inline u32 size_h264d_lb_se_left_ctrl_ar50lt(u32 frame_height) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_height, 16); +} + static inline u32 size_h264d_lb_pe_top_data(u32 frame_width) { return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_pe_top_data_ar50lt(u32 frame_width) +{ + return 64 * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_vsp_top(u32 frame_width) { return (DIV_ROUND_UP(frame_width, 16) << 7); @@ -289,6 +325,7 @@ u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif From 207c29aca005da6853aa58932f07fb005201f8d2 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Fri, 15 May 2026 14:48:13 +0300 Subject: [PATCH 0204/1058] FROMLIST: media: iris: add Gen2 firmware support on the Agatti platform Agatti platform is using HFI Gen1 firmware, which is considered to be legacy firmware branch. Follow the example of the SC7280 platform and extend the driver with supporting both HFI Gen1 and Gen2 firmwares for this platform. Like HFI Gen1 this firmware doesn't have PIPE property (but unlike Gen1 buffer sizes are calculated on the driver side). Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-14-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dikshita Agarwal Signed-off-by: Dmitry Baryshkov --- .../media/platform/qcom/iris/iris_hfi_gen2.c | 613 ++++++++++++++++++ .../platform/qcom/iris/iris_platform_common.h | 1 + .../qcom/iris/iris_platform_vpu_ar50lt.c | 11 +- 3 files changed, 623 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c index acc0ed8adda1a..f89245269e8c1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c @@ -1118,3 +1118,616 @@ const struct iris_firmware_data iris_hfi_gen2_data = { .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; + +static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_dec[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_VP9, + .min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0), + .value = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_VP9, + .min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = TIER, + .min = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH), + .value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .hfi_id = HFI_PROP_TIER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = POC, + .min = 0, + .max = 2, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_PIC_ORDER_CNT_TYPE, + }, + { + .cap_id = CODED_FRAMES, + .min = CODED_FRAMES_PROGRESSIVE, + .max = CODED_FRAMES_PROGRESSIVE, + .step_or_mask = 0, + .value = CODED_FRAMES_PROGRESSIVE, + .hfi_id = HFI_PROP_CODED_FRAMES, + }, + { + .cap_id = BIT_DEPTH, + .min = BIT_DEPTH_8, + .max = BIT_DEPTH_8, + .step_or_mask = 1, + .value = BIT_DEPTH_8, + .hfi_id = HFI_PROP_LUMA_CHROMA_BIT_DEPTH, + }, + { + .cap_id = RAP_FRAME, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_DEC_START_FROM_RAP_FRAME, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, +}; + +static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen2, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = 1, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate_gen2, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = 1, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_peak_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen2, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_u32, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen2, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = IR_TYPE, + .min = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM), + .value = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = IR_PERIOD, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 0, + .flags = CAP_FLAG_OUTPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_ir_period_gen2, + }, +}; + +static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, +}; + +const struct iris_firmware_data iris_hfi_gen2_ar50lt_data = { + .init_hfi_ops = iris_hfi_gen2_sys_ops_init, + + .core_arch = VIDEO_ARCH_LX, + + .inst_fw_caps_dec = inst_fw_cap_gen2_ar50lt_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_dec), + .inst_fw_caps_enc = inst_fw_cap_gen2_ar50lt_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_enc), + .dec_input_config_params_default = + sm8550_vdec_input_config_params_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .dec_input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .dec_input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .dec_input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .dec_input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), + .dec_output_config_params = + sm8550_vdec_output_config_params, + .dec_output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), + .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + .enc_ip_int_buf_tbl = sm8550_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_ip_int_buf_tbl), + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index d1cf596ca349a..3592254d5ff77 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -56,6 +56,7 @@ enum pipe_type { extern const struct iris_firmware_data iris_hfi_gen1_data; extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data; extern const struct iris_firmware_data iris_hfi_gen2_data; +extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data; extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c index 393256f39112b..d9de7dcb59e3a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -13,12 +13,18 @@ #define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10 -const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_s6_desc = { +const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_desc = { .firmware_data = &iris_hfi_gen1_ar50lt_data, .get_vpu_buffer_size = iris_vpu_ar50lt_gen1_buf_size, .fwname = "qcom/venus-6.0/venus.mbn", }; +const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen2_s6_desc = { + .firmware_data = &iris_hfi_gen2_ar50lt_data, + .get_vpu_buffer_size = iris_vpu_ar50lt_gen2_buf_size, + .fwname = "qcom/vpu/ar50lt_p1_gen2_s6.mbn", +}; + static const u32 iris_fmts_ar50lt_dec[] = { [IRIS_FMT_H264] = V4L2_PIX_FMT_H264, [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC, @@ -78,7 +84,8 @@ static struct platform_inst_caps platform_inst_cap_ar50lt = { }; const struct iris_platform_data qcm2290_data = { - .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_s6_desc, + .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_desc, + .firmware_desc_gen2 = &iris_vpu_ar50lt_p1_gen2_s6_desc, .vpu_ops = &iris_vpu_ar50lt_ops, .icc_tbl = iris_icc_info_ar50lt, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt), From 432464b1760069f48b14c22348310ea54ea86bbb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:14 +0300 Subject: [PATCH 0205/1058] FROMLIST: media: venus: skip QCM2290 if Iris driver is enabled As the Iris driver now supports the QCM2290 hardware too, there is a race between Venus and Iris drivers on binding to the corresponding device. Follow the approach used by other platforms and skip QCM2290 in the Venus driver if Iris is enabled. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-15-df3846e74347@oss.qualcomm.com/ Signed-off-by: Dmitry Baryshkov Reviewed-by: Dikshita Agarwal --- drivers/media/platform/qcom/venus/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 243e342b0ae75..3c88594eb1d00 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -1118,7 +1118,6 @@ static const struct venus_resources sc7280_res = { .dec_nodename = "video-decoder", .enc_nodename = "video-encoder", }; -#endif static const struct bw_tbl qcm2290_bw_table_dec[] = { { 352800, 597000, 0, 746000, 0 }, /* 1080p@30 + 720p@30 */ @@ -1169,13 +1168,16 @@ static const struct venus_resources qcm2290_res = { .enc_nodename = "video-encoder", .min_fw = &min_fw, }; +#endif static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, { .compatible = "qcom,msm8939-venus", .data = &msm8939_res, }, { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, +#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_IRIS)) { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, }, +#endif { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, From a05911ad6968c7adf41f14696bd2a61d1e7bd6c6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 15 May 2026 14:48:15 +0300 Subject: [PATCH 0206/1058] FROMLIST: media: iris: constify inst_fw_cap_sm8250_dec Mark inst_fw_cap_sm8250_dec as a const array, the data is read-only. Link: https://lore.kernel.org/all/20260515-iris-ar50lt-v3-16-df3846e74347@oss.qualcomm.com/ Suggested-by: Vishnu Reddy Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_hfi_gen1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c index f57af31dbd9f0..a8819470f7033 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c @@ -13,7 +13,7 @@ #define BITRATE_MAX 160000000 #define BITRATE_STEP 100 -static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { +static const struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { { .cap_id = PIPE, /* .max, .min and .value are set via platform data */ From cc0d08c05590dc6ecf2a8794e9dfe46bcf128c3b Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:07 +0530 Subject: [PATCH 0207/1058] FROMLIST: media: iris: Fix VM count passed to firmware On Glymur, firmware interprets the value written to CPU_CS_SCIACMDARG3 as the number of virtual machines (VMs) and internally adds 1 to it. Writing 1 causes firmware to treat it as 2 VMs. Since only one VM is required, remove this write to leave the register at its reset value of 0. This does not affect other platforms as only Glymur firmware uses this register, earlier platform firmwares ignore it. Link: https://lore.kernel.org/all/20260428-glymur-v3-1-8f28930f47d3@oss.qualcomm.com/ Fixes: abf5bac63f68a ("media: iris: implement the boot sequence of the firmware") Cc: stable@vger.kernel.org Reviewed-by: Vikash Garodia Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/iris_vpu_common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 75dc051cc6cbc..10f164088de14 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -78,7 +78,6 @@ int iris_vpu_boot_firmware(struct iris_core *core) iris_vpu_setup_ucregion_memory_map(core); writel(ctrl_init, core->reg_base + CTRL_INIT); - writel(0x1, core->reg_base + CPU_CS_SCIACMDARG3); while (!ctrl_status && count < max_tries) { ctrl_status = readl(core->reg_base + CTRL_STATUS); From e2a12efa559e78e5fab073aaccc6f853a6e35068 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:13 +0530 Subject: [PATCH 0208/1058] FROMLIST: media: iris: Rename clock and power domain macros to use vcodec prefix The current clock and power domain enum names are too generic. Rename them with a vcodec prefix to make the names more meaningful and to easily accommodate vcodec1 enums for the secondary core for glymur platform. No functional changes intended. Link: https://lore.kernel.org/all/20260428-glymur-v3-7-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../platform/qcom/iris/iris_platform_common.h | 12 +++---- .../platform/qcom/iris/iris_platform_sc7280.h | 10 +++--- .../platform/qcom/iris/iris_platform_sm8250.h | 6 ++-- .../platform/qcom/iris/iris_platform_sm8550.h | 6 ++-- .../platform/qcom/iris/iris_platform_sm8750.h | 12 +++---- .../qcom/iris/iris_platform_vpu_ar50lt.c | 6 ++-- .../qcom/iris/iris_platform_x1p42100.h | 8 ++--- drivers/media/platform/qcom/iris/iris_vpu3x.c | 21 +++++------ drivers/media/platform/qcom/iris/iris_vpu4x.c | 30 ++++++++-------- .../platform/qcom/iris/iris_vpu_ar50lt.c | 27 +++++++------- .../platform/qcom/iris/iris_vpu_common.c | 35 ++++++++++--------- 11 files changed, 89 insertions(+), 84 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 3592254d5ff77..25f56eff16141 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -68,14 +68,14 @@ extern const struct iris_platform_data sm8750_data; extern const struct iris_platform_data x1p42100_data; enum platform_clk_type { - IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ + IRIS_AXI_VCODEC_CLK, IRIS_CTRL_CLK, IRIS_AHB_CLK, - IRIS_HW_CLK, - IRIS_HW_AHB_CLK, - IRIS_AXI1_CLK, + IRIS_VCODEC_CLK, + IRIS_VCODEC_AHB_CLK, + IRIS_AXI_CTRL_CLK, IRIS_CTRL_FREERUN_CLK, - IRIS_HW_FREERUN_CLK, + IRIS_VCODEC_FREERUN_CLK, IRIS_BSE_HW_CLK, IRIS_VPP0_HW_CLK, IRIS_VPP1_HW_CLK, @@ -237,7 +237,7 @@ struct icc_vote_data { enum platform_pm_domain_type { IRIS_CTRL_POWER_DOMAIN, - IRIS_HW_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, IRIS_VPP0_HW_POWER_DOMAIN, IRIS_VPP1_HW_POWER_DOMAIN, IRIS_APV_HW_POWER_DOMAIN, diff --git a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h index 0ec8f334df670..6b783e524b819 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h @@ -16,11 +16,11 @@ static const struct bw_info sc7280_bw_table_dec[] = { static const char * const sc7280_opp_pd_table[] = { "cx" }; static const struct platform_clk_data sc7280_clk_table[] = { - {IRIS_CTRL_CLK, "core" }, - {IRIS_AXI_CLK, "iface" }, - {IRIS_AHB_CLK, "bus" }, - {IRIS_HW_CLK, "vcodec_core" }, - {IRIS_HW_AHB_CLK, "vcodec_bus" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_AHB_CLK, "bus" }, + {IRIS_VCODEC_CLK, "vcodec_core" }, + {IRIS_VCODEC_AHB_CLK, "vcodec_bus" }, }; static const char * const sc7280_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h index 50306043eb8ec..964e1cd920860 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h @@ -16,9 +16,9 @@ static const struct bw_info sm8250_bw_table_dec[] = { static const char * const sm8250_opp_pd_table[] = { "mx", "mmcx" }; static const struct platform_clk_data sm8250_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, }; static const char * const sm8250_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h index 3c9dae995bb24..03a63904579e1 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h @@ -9,9 +9,9 @@ static const char * const sm8550_clk_reset_table[] = { "bus" }; static const struct platform_clk_data sm8550_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, }; static struct platform_inst_caps platform_inst_cap_sm8550 = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h index 719056656a5ba..f843f13251c5c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h @@ -11,12 +11,12 @@ static const char * const sm8750_clk_reset_table[] = { }; static const struct platform_clk_data sm8750_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_AXI1_CLK, "iface1" }, - {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, - {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_AXI_CTRL_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_VCODEC_FREERUN_CLK, "vcodec0_core_freerun" }, }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c index d9de7dcb59e3a..3d8b64d9462f5 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -49,10 +49,10 @@ static const char * const iris_opp_pd_table_ar50lt[] = { "cx" }; static const struct platform_clk_data iris_clk_table_ar50lt[] = { {IRIS_CTRL_CLK, "core" }, - {IRIS_AXI_CLK, "iface" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, {IRIS_AHB_CLK, "bus" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_HW_AHB_CLK, "vcodec0_bus" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_VCODEC_AHB_CLK, "vcodec0_bus" }, {IRIS_THROTTLE_CLK, "throttle" }, }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h index d89acfbc1233d..2c0b0644cd5aa 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h +++ b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h @@ -7,10 +7,10 @@ #define __IRIS_PLATFORM_X1P42100_H__ static const struct platform_clk_data x1p42100_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_BSE_HW_CLK, "vcodec0_bse" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_BSE_HW_CLK, "vcodec0_bse" }, }; static const char *const x1p42100_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index c3b760730c981..0ef3768586523 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -209,7 +209,7 @@ static int iris_vpu33_power_off_controller(struct iris_core *core) disable_power: iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); return 0; } @@ -218,30 +218,31 @@ static int iris_vpu35_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, + core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_FREERUN_CLK); if (ret) goto err_disable_axi_clk; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto err_disable_hw_free_clk; return 0; err_disable_hw_free_clk: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); err_disable_axi_clk: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); return ret; } @@ -250,8 +251,8 @@ static void iris_vpu35_power_off_hw(struct iris_core *core) { iris_vpu33_power_off_hardware(core); - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); } const struct vpu_ops iris_vpu3_ops = { diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 90ccdc0d2a076..d9343a900e93b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -27,7 +27,8 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 { int ret; - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], hw_mode); + ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], + hw_mode); if (ret) return ret; @@ -63,7 +64,7 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP0_HW_POWER_DOMAIN], !hw_mode); restore_hw_domain_mode: - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], !hw_mode); + dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], !hw_mode); return ret; } @@ -162,15 +163,15 @@ static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_v { int ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_FREERUN_CLK); if (ret) goto disable_axi_clock; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto disable_hw_free_run_clock; @@ -198,11 +199,11 @@ static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_v disable_bse_hw_clock: iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); disable_hw_free_run_clock: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); return ret; } @@ -216,9 +217,9 @@ static void iris_vpu4x_disable_hardware_clocks(struct iris_core *core, u32 efuse iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); } static int iris_vpu4x_power_on_hardware(struct iris_core *core) @@ -226,7 +227,8 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, + core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); if (ret) return ret; @@ -267,7 +269,7 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs [IRIS_VPP0_HW_POWER_DOMAIN]); disable_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); return ret; } @@ -345,7 +347,7 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs [IRIS_VPP0_HW_POWER_DOMAIN]); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); } static int iris_vpu4x_set_hwmode(struct iris_core *core) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c index 1af20b067c032..f1a37e8197f55 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c @@ -37,7 +37,7 @@ static void iris_vpu_ar50lt_disable_arp(struct iris_core *core) static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) { iris_disable_unprepare_clock(core, IRIS_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); @@ -46,11 +46,11 @@ static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); + dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], false); iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); } static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) @@ -65,7 +65,7 @@ static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret && ret != -ENOENT) goto err_disable_ctrl_clock; @@ -76,7 +76,7 @@ static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) return 0; err_disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_ctrl_clock: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); err_disable_power: @@ -89,15 +89,16 @@ static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, + core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_AHB_CLK); if (ret) goto err_disable_hw_clock; @@ -108,11 +109,11 @@ static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) return 0; err_disable_hw_ahb_clock: - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); err_disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); return ret; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 10f164088de14..25ab4bb59bdd5 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -216,7 +216,7 @@ int iris_vpu_power_off_controller(struct iris_core *core) disable_power: iris_disable_unprepare_clock(core, IRIS_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); return 0; @@ -224,11 +224,11 @@ int iris_vpu_power_off_controller(struct iris_core *core) void iris_vpu_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], false); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); } void iris_vpu_power_off(struct iris_core *core) @@ -255,7 +255,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) goto err_disable_power; @@ -272,7 +272,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) err_disable_ctrl_clock: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); err_disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); @@ -283,15 +283,16 @@ int iris_vpu_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, + core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_AHB_CLK); if (ret && ret != -ENOENT) goto err_disable_hw_clock; @@ -302,18 +303,18 @@ int iris_vpu_power_on_hw(struct iris_core *core) return 0; err_disable_hw_ahb_clock: - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); err_disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); return ret; } int iris_vpu_set_hwmode(struct iris_core *core) { - return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); + return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], true); } int iris_vpu_switch_to_hwmode(struct iris_core *core) @@ -376,7 +377,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) disable_power: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); @@ -393,7 +394,7 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_CTRL_CLK); if (ret) goto err_disable_power; @@ -410,7 +411,7 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) err_disable_ctrl_free_clk: iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); err_disable_axi1_clk: - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); err_disable_power: iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); From 972ab0ae28349a41f152f473be18ea39806145c2 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:14 +0530 Subject: [PATCH 0209/1058] FROMLIST: media: iris: Use power domain type to look up pd_devs index The pmdomain_tbl was a array of strings holding only the power domain names. Callers had to pass a pd_devs[] pointer indexed directly by the platform_pm_domain_type enum value to iris_enable_power_domains() and iris_disable_power_domains(). A future platform may need to introduce a new enum value that aliases an existing one (e.g. IRIS_VCODEC1_POWER_DOMAIN aliasing the IRIS_VPP0_HW_POWER_DOMAIN on Glymur), which would break the assumption that enum values map 1:1 to pd_devs[] indices. To fix this, replace the string array with a new struct platform_pd_data that pairs each power domain name with its platform_pm_domain_type. Add a helper iris_get_pd_index_by_type() that walks this table and returns the correct pd_devs[] index for a given type. Update iris_enable_power_domains() and iris_disable_power_domains() to accept a platform_pm_domain_type instead of a struct device pointer. They now call the helper internally to resolve the index, removing the need for callers to do the index lookup themselves. This prepares the driver for adding new platforms where power domain enum values cannot be used directly as pd_devs[] indices. Link: https://lore.kernel.org/all/20260428-glymur-v3-8-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../platform/qcom/iris/iris_platform_common.h | 9 +++- .../platform/qcom/iris/iris_platform_vpu2.c | 18 +++++-- .../platform/qcom/iris/iris_platform_vpu3x.c | 27 ++++++---- .../qcom/iris/iris_platform_vpu_ar50lt.c | 15 ++++-- drivers/media/platform/qcom/iris/iris_probe.c | 4 +- .../media/platform/qcom/iris/iris_resources.c | 44 +++++++++++++++- .../media/platform/qcom/iris/iris_resources.h | 6 ++- drivers/media/platform/qcom/iris/iris_vpu3x.c | 7 ++- drivers/media/platform/qcom/iris/iris_vpu4x.c | 52 +++++++------------ .../platform/qcom/iris/iris_vpu_ar50lt.c | 15 +++--- .../platform/qcom/iris/iris_vpu_common.c | 23 ++++---- 11 files changed, 136 insertions(+), 84 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 25f56eff16141..488356307c302 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -295,6 +295,12 @@ struct iris_firmware_desc { const char *fwname; }; +struct platform_pd_data { + enum platform_pm_domain_type *pd_types; + const char **pd_names; + u32 pd_count; +}; + struct iris_platform_data { const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2; @@ -303,8 +309,7 @@ struct iris_platform_data { unsigned int icc_tbl_size; const struct bw_info *bw_tbl_dec; unsigned int bw_tbl_dec_size; - const char * const *pmdomain_tbl; - unsigned int pmdomain_tbl_size; + const struct platform_pd_data *pmdomain_tbl; const char * const *opp_pd_tbl; unsigned int opp_pd_tbl_size; const struct platform_clk_data *clk_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index e2fddc29abc72..3bfafa705291c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -61,7 +61,17 @@ static const struct icc_info iris_icc_info_vpu2[] = { static const char * const iris_clk_reset_table_vpu2[] = { "bus", "core" }; -static const char * const iris_pmdomain_table_vpu2[] = { "venus", "vcodec0" }; +static const struct platform_pd_data iris_pmdomain_table_vpu2 = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; static const struct tz_cp_config tz_cp_config_vpu2[] = { { @@ -80,8 +90,7 @@ const struct iris_platform_data sc7280_data = { .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), .bw_tbl_dec = sc7280_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .pmdomain_tbl = &iris_pmdomain_table_vpu2, .opp_pd_tbl = sc7280_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sc7280_opp_pd_table), .clk_tbl = sc7280_clk_table, @@ -113,8 +122,7 @@ const struct iris_platform_data sm8250_data = { .clk_rst_tbl_size = ARRAY_SIZE(iris_clk_reset_table_vpu2), .bw_tbl_dec = sm8250_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .pmdomain_tbl = &iris_pmdomain_table_vpu2, .opp_pd_tbl = sm8250_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sm8250_opp_pd_table), .clk_tbl = sm8250_clk_table, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 64cf182d67ccd..643331f1b5f31 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -69,7 +69,17 @@ static const struct bw_info iris_bw_table_dec_vpu3x[] = { { ((1920 * 1080) / 256) * 30, 294000 }, }; -static const char * const iris_pmdomain_table_vpu3x[] = { "venus", "vcodec0" }; +static const struct platform_pd_data iris_pmdomain_table_vpu3x = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; static const char * const iris_opp_pd_table_vpu3x[] = { "mxc", "mmcx" }; @@ -100,8 +110,7 @@ const struct iris_platform_data qcs8300_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -131,8 +140,7 @@ const struct iris_platform_data sm8550_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -170,8 +178,7 @@ const struct iris_platform_data sm8650_data = { .controller_rst_tbl_size = ARRAY_SIZE(sm8650_controller_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -201,8 +208,7 @@ const struct iris_platform_data sm8750_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8750_clk_table, @@ -238,8 +244,7 @@ const struct iris_platform_data x1p42100_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = x1p42100_clk_table, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c index 3d8b64d9462f5..8e97f7191eac7 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -43,7 +43,17 @@ static const struct icc_info iris_icc_info_ar50lt[] = { { "video-mem", 1000, 6500000 }, }; -static const char * const iris_pmdomain_table_ar50lt[] = { "venus", "vcodec0" }; +static const struct platform_pd_data iris_pmdomain_table_ar50lt = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; static const char * const iris_opp_pd_table_ar50lt[] = { "cx" }; @@ -91,8 +101,7 @@ const struct iris_platform_data qcm2290_data = { .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt), .bw_tbl_dec = iris_bw_table_dec_ar50lt, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_ar50lt), - .pmdomain_tbl = iris_pmdomain_table_ar50lt, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_ar50lt), + .pmdomain_tbl = &iris_pmdomain_table_ar50lt, .opp_pd_tbl = iris_opp_pd_table_ar50lt, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_ar50lt), .clk_tbl = iris_clk_table_ar50lt, diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 472d9e293ece0..ebe17abfc4663 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -44,8 +44,8 @@ static int iris_init_power_domains(struct iris_core *core) int ret; struct dev_pm_domain_attach_data iris_pd_data = { - .pd_names = core->iris_platform_data->pmdomain_tbl, - .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, + .pd_names = core->iris_platform_data->pmdomain_tbl->pd_names, + .num_pd_names = core->iris_platform_data->pmdomain_tbl->pd_count, .pd_flags = PD_FLAG_NO_DEV_LINK, }; diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index caeaf199cef74..129cb9a481372 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -72,10 +72,43 @@ int iris_opp_set_rate(struct device *dev, unsigned long freq) return dev_pm_opp_set_opp(dev, opp); } -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) +static int iris_get_pd_index_by_type(struct iris_core *core, enum platform_pm_domain_type pd_type) { + const struct platform_pd_data *pd_tbl; + u32 pd_count, i; + + pd_tbl = core->iris_platform_data->pmdomain_tbl; + pd_count = core->iris_platform_data->pmdomain_tbl->pd_count; + + for (i = 0; i < pd_count; i++) { + if (pd_tbl->pd_types[i] == pd_type) + return i; + } + + return -EINVAL; +} + +int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, bool hwmode) +{ + int pd_index = iris_get_pd_index_by_type(core, pd_type); + + if (pd_index < 0) + return pd_index; + + return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[pd_index], hwmode); +} + +int iris_enable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type) +{ + int pd_index = iris_get_pd_index_by_type(core, pd_type); + struct device *pd_dev; int ret; + if (pd_index < 0) + return pd_index; + + pd_dev = core->pmdomain_tbl->pd_devs[pd_index]; + ret = iris_opp_set_rate(core->dev, ULONG_MAX); if (ret) return ret; @@ -87,10 +120,17 @@ int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) return ret; } -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev) +int iris_disable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type) { + int pd_index = iris_get_pd_index_by_type(core, pd_type); + struct device *pd_dev; int ret; + if (pd_index < 0) + return pd_index; + + pd_dev = core->pmdomain_tbl->pd_devs[pd_index]; + ret = iris_opp_set_rate(core->dev, 0); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index 6bfbd2dc6db09..d5692e4694b14 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -9,11 +9,13 @@ struct iris_core; int iris_opp_set_rate(struct device *dev, unsigned long freq); -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev); -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev); +int iris_enable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type); +int iris_disable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type); int iris_unset_icc_bw(struct iris_core *core); int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); +int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, + bool hwmode); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 0ef3768586523..a8a39196c0833 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -208,7 +208,7 @@ static int iris_vpu33_power_off_controller(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); return 0; @@ -218,8 +218,7 @@ static int iris_vpu35_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; @@ -242,7 +241,7 @@ static int iris_vpu35_power_on_hw(struct iris_core *core) err_disable_axi_clk: iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index d9343a900e93b..946c165ac9342 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -27,28 +27,24 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 { int ret; - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], - hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, hw_mode); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VPP0_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_hw_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VPP1_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_vpp0_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_APV_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_APV_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_vpp1_domain_mode; } @@ -57,14 +53,12 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 restore_vpp1_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP1_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VPP1_HW_POWER_DOMAIN, !hw_mode); restore_vpp0_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP0_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VPP0_HW_POWER_DOMAIN, !hw_mode); restore_hw_domain_mode: - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, !hw_mode); return ret; } @@ -73,8 +67,7 @@ static int iris_vpu4x_power_on_apv(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); if (ret) return ret; @@ -85,7 +78,7 @@ static int iris_vpu4x_power_on_apv(struct iris_core *core) return 0; disable_apv_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); return ret; } @@ -140,7 +133,7 @@ static void iris_vpu4x_power_off_apv(struct iris_core *core) disable_clocks_and_power: iris_disable_unprepare_clock(core, IRIS_APV_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); } static void iris_vpu4x_ahb_sync_reset_apv(struct iris_core *core) @@ -227,21 +220,18 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); if (ret) goto disable_hw_power_domain; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); if (ret) goto disable_vpp0_power_domain; } @@ -262,14 +252,12 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) iris_vpu4x_disable_hardware_clocks(core, efuse_value); disable_vpp1_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); disable_vpp0_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); disable_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } @@ -340,14 +328,12 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) iris_vpu4x_disable_hardware_clocks(core, efuse_value); if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); } static int iris_vpu4x_set_hwmode(struct iris_core *core) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c index f1a37e8197f55..11369c847711c 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c @@ -39,25 +39,25 @@ static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return 0; } static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], false); + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK); iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); } static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); if (ret) return ret; @@ -80,7 +80,7 @@ static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) err_disable_ctrl_clock: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return ret; } @@ -89,8 +89,7 @@ static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; @@ -113,7 +112,7 @@ static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) err_disable_hw_clock: iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 25ab4bb59bdd5..ac9881e2cdc29 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -217,15 +217,15 @@ int iris_vpu_power_off_controller(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return 0; } void iris_vpu_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], false); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); @@ -247,7 +247,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); if (ret) return ret; @@ -274,7 +274,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) err_disable_axi_clock: iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return ret; } @@ -283,8 +283,7 @@ int iris_vpu_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; @@ -307,14 +306,14 @@ int iris_vpu_power_on_hw(struct iris_core *core) err_disable_hw_clock: iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } int iris_vpu_set_hwmode(struct iris_core *core) { - return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VCODEC_POWER_DOMAIN], true); + return iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, true); } int iris_vpu_switch_to_hwmode(struct iris_core *core) @@ -379,7 +378,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); reset_control_bulk_reset(clk_rst_tbl_size, core->resets); @@ -390,7 +389,7 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); if (ret) return ret; @@ -413,7 +412,7 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) err_disable_axi1_clk: iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return ret; } From 8546813c371769b56e6cfcaf4edc4b1d4023865b Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:15 +0530 Subject: [PATCH 0210/1058] FROMLIST: media: iris: Add power sequence for Glymur Glymur has a secondary video codec core (vcodec1), equivalent to the primary core (vcodec0), but with independent power domains, clocks, and reset lines. Reuse the existing code wherever possible and add power sequence for vcodec1. Link: https://lore.kernel.org/all/20260428-glymur-v3-9-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../platform/qcom/iris/iris_platform_common.h | 4 + drivers/media/platform/qcom/iris/iris_vpu3x.c | 139 ++++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.h | 1 + .../qcom/iris/iris_vpu_register_defines.h | 7 + 4 files changed, 151 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 488356307c302..0bbe0fbd693cb 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -81,6 +81,9 @@ enum platform_clk_type { IRIS_VPP1_HW_CLK, IRIS_APV_HW_CLK, IRIS_THROTTLE_CLK, + IRIS_AXI_VCODEC1_CLK, + IRIS_VCODEC1_CLK, + IRIS_VCODEC1_FREERUN_CLK, }; struct platform_clk_data { @@ -241,6 +244,7 @@ enum platform_pm_domain_type { IRIS_VPP0_HW_POWER_DOMAIN, IRIS_VPP1_HW_POWER_DOMAIN, IRIS_APV_HW_POWER_DOMAIN, + IRIS_VCODEC1_POWER_DOMAIN, }; struct iris_firmware_data { diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index a8a39196c0833..40fa9ebada78a 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -27,6 +27,16 @@ static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) return pwr_status ? false : true; } +static bool iris_vpu36_hw1_power_collapsed(struct iris_core *core) +{ + u32 value, pwr_status; + + value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); + pwr_status = value & BIT(4); + + return !pwr_status; +} + static void iris_vpu3_power_off_hardware(struct iris_core *core) { u32 reg_val = 0, value, i; @@ -254,6 +264,124 @@ static void iris_vpu35_power_off_hw(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); } +static int iris_vpu36_power_on_hw1(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC1_CLK); + if (ret) + goto err_disable_hw1_power; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC1_FREERUN_CLK); + if (ret) + goto err_disable_axi1_clk; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC1_CLK); + if (ret) + goto err_disable_hw1_free_clk; + + return 0; + +err_disable_hw1_free_clk: + iris_disable_unprepare_clock(core, IRIS_VCODEC1_FREERUN_CLK); +err_disable_axi1_clk: + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC1_CLK); +err_disable_hw1_power: + iris_disable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); + + return ret; +} + +static int iris_vpu36_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_vpu35_power_on_hw(core); + if (ret) + return ret; + + ret = iris_vpu36_power_on_hw1(core); + if (ret) + goto err_power_off_hw; + + return 0; + +err_power_off_hw: + iris_vpu35_power_off_hw(core); + + return ret; +} + +static void iris_vpu36_power_off_hw1(struct iris_core *core) +{ + u32 value, i; + int ret; + + if (iris_vpu36_hw1_power_collapsed(core)) + goto disable_power; + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + if (value) + writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { + ret = readl_poll_timeout(core->reg_base + VCODEC1_SS_IDLE_STATUSN + 4 * i, + value, value & DMA_NOC_IDLE, 2000, 20000); + if (ret) + goto disable_power; + } + + writel(REQ_VCODEC1_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, + value, value & NOC_LPI_VCODEC1_STATUS_DONE, 2000, 20000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + writel(VCODEC1_BRIDGE_SW_RESET | VCODEC1_BRIDGE_HW_RESET_DISABLE, core->reg_base + + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(VCODEC1_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + +disable_power: + iris_genpd_set_hwmode(core, IRIS_VCODEC1_POWER_DOMAIN, false); + iris_disable_unprepare_clock(core, IRIS_VCODEC1_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC1_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC1_CLK); + iris_disable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); +} + +static void iris_vpu36_power_off_hw(struct iris_core *core) +{ + iris_vpu35_power_off_hw(core); + iris_vpu36_power_off_hw1(core); +} + +static int iris_vpu36_set_hwmode(struct iris_core *core) +{ + int ret; + + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, true); + if (ret) + return ret; + + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC1_POWER_DOMAIN, true); + if (ret) + goto error_disable_hwmode; + + return 0; + +error_disable_hwmode: + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); + + return ret; +} + const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_on_hw = iris_vpu_power_on_hw, @@ -287,3 +415,14 @@ const struct vpu_ops iris_vpu35_ops = { .set_preset_registers = iris_vpu_set_preset_registers, .interrupt_init = iris_vpu_interrupt_init, }; + +const struct vpu_ops iris_vpu36_ops = { + .power_off_hw = iris_vpu36_power_off_hw, + .power_on_hw = iris_vpu36_power_on_hw, + .power_off_controller = iris_vpu35_vpu4x_power_off_controller, + .power_on_controller = iris_vpu35_vpu4x_power_on_controller, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, + .set_hwmode = iris_vpu36_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, +}; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index f00e2de5fa537..8d954426a9482 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -12,6 +12,7 @@ extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; extern const struct vpu_ops iris_vpu35_ops; +extern const struct vpu_ops iris_vpu36_ops; extern const struct vpu_ops iris_vpu4x_ops; extern const struct vpu_ops iris_vpu_ar50lt_ops; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 4fffa094c52fe..dc29e950f01cc 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -7,6 +7,7 @@ #define __IRIS_VPU_REGISTER_DEFINES_H__ #define VCODEC_BASE_OFFS 0x00000000 +#define VCODEC1_BASE_OFFS 0x00040000 #define AON_MVP_NOC_RESET 0x0001F000 #define CPU_BASE_OFFS 0x000A0000 #define WRAPPER_BASE_OFFS 0x000B0000 @@ -14,6 +15,8 @@ #define AON_BASE_OFFS 0x000E0000 #define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) +#define VCODEC1_SS_IDLE_STATUSN (VCODEC1_BASE_OFFS + 0x70) +#define DMA_NOC_IDLE BIT(22) #define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) @@ -35,6 +38,8 @@ #define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) #define CORE_BRIDGE_SW_RESET BIT(0) #define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) +#define VCODEC1_BRIDGE_SW_RESET BIT(2) +#define VCODEC1_BRIDGE_HW_RESET_DISABLE BIT(3) #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) #define MSK_SIGNAL_FROM_TENSILICA BIT(0) @@ -51,11 +56,13 @@ #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) +#define REQ_VCODEC1_POWER_DOWN_PREP BIT(1) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) #define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ #define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ #define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ +#define NOC_LPI_VCODEC1_STATUS_DONE BIT(8) #define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) #define WRAPPER_CORE_POWER_STATUS (WRAPPER_BASE_OFFS + 0x80) From 59a6e61eb57898d03549b91c43c5eb0861cf8baa Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:16 +0530 Subject: [PATCH 0211/1058] FROMLIST: media: iris: Add support to select core for dual core platforms On platforms with dual vcodec cores, select the hardware core for a session based on current load. Assign the session to vcodec0 if its MBPF/MBPS capacity allows it, otherwise assign to vcodec1. Communicate the selected core to firmware using the new HFI_PROP_CORE_ID property. Link: https://lore.kernel.org/all/20260428-glymur-v3-10-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../media/platform/qcom/iris/iris_common.c | 10 ++ .../media/platform/qcom/iris/iris_common.h | 1 + drivers/media/platform/qcom/iris/iris_core.h | 5 + .../platform/qcom/iris/iris_hfi_common.h | 1 + .../qcom/iris/iris_hfi_gen2_command.c | 19 ++++ .../qcom/iris/iris_hfi_gen2_defines.h | 1 + .../media/platform/qcom/iris/iris_instance.h | 2 + .../platform/qcom/iris/iris_platform_common.h | 1 + drivers/media/platform/qcom/iris/iris_power.c | 11 ++- drivers/media/platform/qcom/iris/iris_utils.c | 91 +++++++++++++++---- drivers/media/platform/qcom/iris/iris_vb2.c | 4 + drivers/media/platform/qcom/iris/iris_vidc.c | 6 +- 12 files changed, 129 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c index 25836561bcf3e..dade0273717a2 100644 --- a/drivers/media/platform/qcom/iris/iris_common.c +++ b/drivers/media/platform/qcom/iris/iris_common.c @@ -46,6 +46,16 @@ void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) inst->metadata_idx++; } +int iris_set_core_id(struct iris_inst *inst) +{ + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; + + if (!inst->core->iris_platform_data->dual_core) + return 0; + + return hfi_ops->session_set_core_id(inst, inst->core_id); +} + int iris_process_streamon_input(struct iris_inst *inst) { const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h index b2a27b781c9ac..34e32c60f7687 100644 --- a/drivers/media/platform/qcom/iris/iris_common.h +++ b/drivers/media/platform/qcom/iris/iris_common.h @@ -11,6 +11,7 @@ struct iris_buffer; int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf); void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_set_core_id(struct iris_inst *inst); int iris_process_streamon_input(struct iris_inst *inst); int iris_process_streamon_output(struct iris_inst *inst); int iris_session_streamoff(struct iris_inst *inst, u32 plane); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 24da60448cf24..e668d5c262167 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -32,6 +32,11 @@ enum domain_type { struct qcom_ubwc_cfg_data; +enum iris_vcodec_core_id { + IRIS_VCODEC0 = 1, + IRIS_VCODEC1, +}; + /** * struct iris_core - holds core parameters valid for all instances * diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 16099f9a25b65..5841e5f9c1228 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -132,6 +132,7 @@ struct iris_hfi_session_ops { int (*session_drain)(struct iris_inst *inst, u32 plane); int (*session_resume_drain)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); + int (*session_set_core_id)(struct iris_inst *inst, u32 core_id); }; struct hfi_subscription_params { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index ca2954f8bd3ad..e73743a391e0f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -1360,6 +1360,24 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i inst_hfi_gen2->packet->size); } +static int iris_hfi_gen2_set_core_id(struct iris_inst *inst, u32 core_id) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 payload = core_id; + + iris_hfi_gen2_packet_session_command(inst, + HFI_PROP_CORE_ID, + HFI_HOST_FLAGS_NONE, + HFI_PORT_NONE, + inst->session_id, + HFI_PAYLOAD_U32, + &payload, + sizeof(u32)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_open = iris_hfi_gen2_session_open, .session_set_config_params = iris_hfi_gen2_session_set_config_params, @@ -1373,6 +1391,7 @@ static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_drain = iris_hfi_gen2_session_drain, .session_resume_drain = iris_hfi_gen2_session_resume_drain, .session_close = iris_hfi_gen2_session_close, + .session_set_core_id = iris_hfi_gen2_set_core_id, }; static struct iris_inst *iris_hfi_gen2_get_instance(void) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 776b21cd11b2c..2e374c2005ef4 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -56,6 +56,7 @@ #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 +#define HFI_PROP_CORE_ID 0x030001a9 enum hfi_rate_control { HFI_RC_VBR_CFR = 0x00000000, diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index a770331d16757..585aa7c51fb0c 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -36,6 +36,7 @@ enum iris_fmt_type_cap { * * @list: used for attach an instance to the core * @core: pointer to core structure + * @core_id: specifies the hardware core on which the session runs * @session_id: id of current video session * @hfi_session_ops: iris HFI session ops * @ctx_q_lock: lock to serialize queues related ioctls @@ -83,6 +84,7 @@ enum iris_fmt_type_cap { struct iris_inst { struct list_head list; struct iris_core *core; + u32 core_id; u32 session_id; const struct iris_hfi_session_ops *hfi_session_ops; struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 0bbe0fbd693cb..880b94b6a171c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -339,6 +339,7 @@ struct iris_platform_data { u32 max_core_mbpf; /* max number of macroblocks per second supported */ u32 max_core_mbps; + bool dual_core; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_power.c b/drivers/media/platform/qcom/iris/iris_power.c index 91aa21d4070eb..0e116c63f529d 100644 --- a/drivers/media/platform/qcom/iris/iris_power.c +++ b/drivers/media/platform/qcom/iris/iris_power.c @@ -77,9 +77,9 @@ static int iris_vote_interconnects(struct iris_inst *inst) static int iris_set_clocks(struct iris_inst *inst) { + u64 vcodec0_freq = 0, vcodec1_freq = 0; struct iris_core *core = inst->core; struct iris_inst *instance; - u64 freq = 0; int ret; mutex_lock(&core->lock); @@ -87,11 +87,14 @@ static int iris_set_clocks(struct iris_inst *inst) if (!instance->max_input_data_size) continue; - freq += instance->power.min_freq; + if (instance->core_id == IRIS_VCODEC0) + vcodec0_freq += instance->power.min_freq; + else if (instance->core_id == IRIS_VCODEC1) + vcodec1_freq += instance->power.min_freq; } - core->power.clk_freq = freq; - ret = iris_opp_set_rate(core->dev, freq); + core->power.clk_freq = vcodec0_freq > vcodec1_freq ? vcodec0_freq : vcodec1_freq; + ret = iris_opp_set_rate(core->dev, core->power.clk_freq); mutex_unlock(&core->lock); return ret; diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c index ba5c8dc1280c2..7ebe4052ec41d 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.c +++ b/drivers/media/platform/qcom/iris/iris_utils.c @@ -101,40 +101,95 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) return NULL; } +static u32 iris_get_mbps(struct iris_inst *inst) +{ + u32 fps = max(inst->frame_rate, inst->operating_rate); + + return iris_get_mbpf(inst) * fps; +} + +static void iris_get_core_load(struct iris_core *core, u32 *core_load, u32 *core_session, bool mbpf) +{ + bool dual_core = core->iris_platform_data->dual_core; + struct iris_inst *inst; + u32 load; + + core_load[0] = 0; + core_load[1] = 0; + core_session[0] = 0; + core_session[1] = 0; + + list_for_each_entry(inst, &core->instances, list) { + if (mbpf) + load = iris_get_mbpf(inst); + else + load = iris_get_mbps(inst); + + if (inst->core_id == IRIS_VCODEC0) { + core_load[0] += load; + core_session[0]++; + } else if (dual_core && inst->core_id == IRIS_VCODEC1) { + core_load[1] += load; + core_session[1]++; + } + } +} + +static int iris_select_core_id(struct iris_inst *inst, u32 *core_load, u32 *core_session, + u32 max_load, u32 new_load) +{ + u32 max_session = inst->core->iris_platform_data->max_session_count; + bool dual_core = inst->core->iris_platform_data->dual_core; + u32 core_index; + + core_index = (core_load[0] > core_load[1] && dual_core) ? 1 : 0; + + if (core_session[core_index] >= max_session) + core_index = core_index == 0 && dual_core ? 1 : 0; + + if (core_session[core_index] >= max_session) + return -ENOMEM; + + if (core_load[core_index] + new_load <= max_load) + inst->core_id = core_index == 0 ? IRIS_VCODEC0 : IRIS_VCODEC1; + else + return -ENOMEM; + + return 0; +} + int iris_check_core_mbpf(struct iris_inst *inst) { + u32 max_core_mbpf = inst->core->iris_platform_data->max_core_mbpf; + u32 core_mbpf[2], core_session[2], new_mbpf; struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbpf = 0; + int ret; mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) - total_mbpf += iris_get_mbpf(instance); + inst->core_id = 0; + iris_get_core_load(inst->core, core_mbpf, core_session, true); + new_mbpf = iris_get_mbpf(inst); + ret = iris_select_core_id(inst, core_mbpf, core_session, max_core_mbpf, new_mbpf); mutex_unlock(&core->lock); - if (total_mbpf > core->iris_platform_data->max_core_mbpf) - return -ENOMEM; - - return 0; + return ret; } int iris_check_core_mbps(struct iris_inst *inst) { + u32 max_core_mbps = inst->core->iris_platform_data->max_core_mbps; + u32 core_mbps[2] = {0, 0}, core_session[2], new_mbps; struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbps = 0, fps = 0; + int ret; mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) { - fps = max(instance->frame_rate, instance->operating_rate); - total_mbps += iris_get_mbpf(instance) * fps; - } + inst->core_id = 0; + iris_get_core_load(inst->core, core_mbps, core_session, false); + new_mbps = iris_get_mbps(inst); + ret = iris_select_core_id(inst, core_mbps, core_session, max_core_mbps, new_mbps); mutex_unlock(&core->lock); - if (total_mbps > core->iris_platform_data->max_core_mbps) - return -ENOMEM; - - return 0; + return ret; } bool is_rotation_90_or_270(struct iris_inst *inst) diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index a2ea2d67f60d0..dbb89396e6514 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -176,6 +176,10 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto error; + ret = iris_set_core_id(inst); + if (ret) + goto error; + if (V4L2_TYPE_IS_OUTPUT(q->type)) { if (inst->domain == DECODER) ret = iris_vdec_streamon_input(inst); diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 372408b894c19..19d4db07d3bca 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -42,16 +42,20 @@ static void iris_v4l2_fh_deinit(struct iris_inst *inst, struct file *filp) static void iris_add_session(struct iris_inst *inst) { + u32 max_session_count = inst->core->iris_platform_data->max_session_count; struct iris_core *core = inst->core; struct iris_inst *iter; u32 count = 0; + if (inst->core->iris_platform_data->dual_core) + max_session_count *= 2; + mutex_lock(&core->lock); list_for_each_entry(iter, &core->instances, list) count++; - if (count < core->iris_platform_data->max_session_count) + if (count < max_session_count) list_add_tail(&inst->list, &core->instances); mutex_unlock(&core->lock); From d0df64f66966221421392f79ca2a16469807d8ba Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:17 +0530 Subject: [PATCH 0212/1058] FROMLIST: media: iris: Add platform data for glymur On glymur platform, the iris core shares most properties with the iris core on the SM8550 platform. The major difference is that glymur integrates two codec cores (vcodec0 and vcodec1), while SM8550 has only one. Add glymur specific platform data, reusing SM8550 definitions wherever applicable. Link: https://lore.kernel.org/all/20260428-glymur-v3-11-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/Makefile | 1 + .../platform/qcom/iris/iris_platform_common.h | 5 ++ .../platform/qcom/iris/iris_platform_glymur.c | 71 +++++++++++++++++++ .../platform/qcom/iris/iris_platform_glymur.h | 15 ++++ .../platform/qcom/iris/iris_platform_vpu3x.c | 36 ++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 ++ 6 files changed, 132 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_glymur.c create mode 100644 drivers/media/platform/qcom/iris/iris_platform_glymur.h diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index bbd1f724963e6..4a70e124e75f6 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -12,6 +12,7 @@ qcom-iris-objs += iris_buffer.o \ iris_hfi_gen2_packet.o \ iris_hfi_gen2_response.o \ iris_hfi_queue.o \ + iris_platform_glymur.o \ iris_platform_vpu2.o \ iris_platform_vpu3x.o \ iris_platform_vpu_ar50lt.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 880b94b6a171c..5e38b48bd502b 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -42,6 +42,10 @@ struct iris_inst; #define BITRATE_DEFAULT_AR50LT 20000000 #define MIN_QP_8BIT_AR50LT 0 +#define VIDEO_REGION_SECURE_FW_REGION_ID 0 +#define VIDEO_REGION_VM0_SECURE_NP_ID 1 +#define VIDEO_REGION_VM0_NONSECURE_NP_ID 5 + enum stage_type { STAGE_1 = 1, STAGE_2 = 2, @@ -58,6 +62,7 @@ extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data; extern const struct iris_firmware_data iris_hfi_gen2_data; extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data; +extern const struct iris_platform_data glymur_data; extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; extern const struct iris_platform_data sc7280_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.c b/drivers/media/platform/qcom/iris/iris_platform_glymur.c new file mode 100644 index 0000000000000..194431665e077 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_platform_common.h" +#include "iris_platform_glymur.h" + +const struct platform_clk_data iris_glymur_clk_table[] = { + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_AXI_CTRL_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_VCODEC_FREERUN_CLK, "vcodec0_core_freerun" }, + {IRIS_AXI_VCODEC1_CLK, "iface2" }, + {IRIS_VCODEC1_CLK, "vcodec1_core" }, + {IRIS_VCODEC1_FREERUN_CLK, "vcodec1_core_freerun" }, +}; + +const char * const iris_glymur_clk_reset_table[] = { + "bus0", + "bus1", + "core", + "vcodec0_core", + "bus2", + "vcodec1_core", +}; + +const char * const iris_glymur_opp_clk_table[] = { + "vcodec0_core", + "vcodec1_core", + "core", + NULL, +}; + +const struct platform_pd_data iris_glymur_pmdomain_table = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + IRIS_VCODEC1_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + "vcodec1", + }, + .pd_count = 3, +}; + +const struct tz_cp_config iris_glymur_tz_cp_config[] = { + { + .cp_start = VIDEO_REGION_SECURE_FW_REGION_ID, + .cp_size = 0, + .cp_nonpixel_start = 0, + .cp_nonpixel_size = 0x1000000, + }, + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x1000000, + .cp_nonpixel_size = 0x24800000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x25800000, + .cp_nonpixel_size = 0xda600000, + }, +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.h b/drivers/media/platform/qcom/iris/iris_platform_glymur.h new file mode 100644 index 0000000000000..875a3c65c58f1 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_PLATFORM_GLYMUR_H__ +#define __IRIS_PLATFORM_GLYMUR_H__ + +extern const struct platform_clk_data iris_glymur_clk_table[9]; +extern const char * const iris_glymur_clk_reset_table[6]; +extern const char * const iris_glymur_opp_clk_table[4]; +extern const struct platform_pd_data iris_glymur_pmdomain_table; +extern const struct tz_cp_config iris_glymur_tz_cp_config[3]; + +#endif /* __IRIS_PLATFORM_GLYMUR_H__ */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 643331f1b5f31..8763a78381c2e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -12,6 +12,7 @@ #include "iris_vpu_buffer.h" #include "iris_vpu_common.h" +#include "iris_platform_glymur.h" #include "iris_platform_qcs8300.h" #include "iris_platform_sm8550.h" #include "iris_platform_sm8650.h" @@ -50,6 +51,12 @@ static const struct iris_firmware_desc iris_vpu35_p4_gen2_desc = { .fwname = "qcom/vpu/vpu35_p4.mbn", }; +const struct iris_firmware_desc iris_vpu36_p4_s7_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu_buf_size, + .fwname = "qcom/vpu/vpu36_p4_s7.mbn", +}; + static const u32 iris_fmts_vpu3x_dec[] = { [IRIS_FMT_H264] = V4L2_PIX_FMT_H264, [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC, @@ -262,3 +269,32 @@ const struct iris_platform_data x1p42100_data = { .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, }; + +const struct iris_platform_data glymur_data = { + .firmware_desc_gen2 = &iris_vpu36_p4_s7_gen2_desc, + .vpu_ops = &iris_vpu36_ops, + .icc_tbl = iris_icc_info_vpu3x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), + .clk_rst_tbl = iris_glymur_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(iris_glymur_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu3x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), + .pmdomain_tbl = &iris_glymur_pmdomain_table, + .opp_pd_tbl = iris_opp_pd_table_vpu3x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), + .clk_tbl = iris_glymur_clk_table, + .clk_tbl_size = ARRAY_SIZE(iris_glymur_clk_table), + .opp_clk_tbl = iris_glymur_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffe00000 - 1, + .inst_iris_fmts = iris_fmts_vpu3x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = iris_glymur_tz_cp_config, + .tz_cp_config_data_size = ARRAY_SIZE(iris_glymur_tz_cp_config), + .num_vpp_pipe = 4, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((8192 * 4320) / 256) * 60, + .dual_core = true, +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index ebe17abfc4663..3813cf48028e1 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -356,6 +356,10 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,glymur-iris", + .data = &glymur_data, + }, { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_data, From 98928e8e787ffb78f50208a53d205d737d618339 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 28 Apr 2026 09:24:08 +0530 Subject: [PATCH 0213/1058] FROMLIST: dt-bindings: media: qcom,glymur-iris: Add glymur video codec Add device tree binding for the Qualcomm Glymur Iris video codec. Glymur is a new generation of video IP that introduces a dual-core architecture. The second core brings its own power domain, clocks, and reset lines, requiring additional power domains and clocks in the power sequence. To accommodate glymur clock and power resources requirement, the maxItems constraints in qcom,venus-common.yaml are relaxed. This allows the glymur binding to inherit from the common venus schema without duplicating shared properties. Link: https://lore.kernel.org/all/20260428-glymur-v3-2-8f28930f47d3@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../bindings/media/qcom,glymur-iris.yaml | 211 ++++++++++++++++++ .../bindings/media/qcom,venus-common.yaml | 8 +- include/dt-bindings/media/qcom,glymur-iris.h | 11 + 3 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml create mode 100644 include/dt-bindings/media/qcom,glymur-iris.h diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml new file mode 100644 index 0000000000000..3c5305b688ec7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur SoC Iris video encoder and decoder + +maintainers: + - Vishnu Reddy + +description: + The Iris video processing unit on Qualcomm Glymur SoC is a video encode and + decode accelerator. + +properties: + compatible: + const: qcom,glymur-iris + + clocks: + maxItems: 9 + + clock-names: + items: + - const: iface + - const: core + - const: vcodec0_core + - const: iface1 + - const: core_freerun + - const: vcodec0_core_freerun + - const: iface2 + - const: vcodec1_core + - const: vcodec1_core_freerun + + dma-coherent: true + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + iommus: + maxItems: 4 + + iommu-map: + maxItems: 1 + + operating-points-v2: true + opp-table: + type: object + + power-domains: + maxItems: 5 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vcodec1 + + resets: + maxItems: 6 + + reset-names: + items: + - const: bus0 + - const: bus1 + - const: core + - const: vcodec0_core + - const: bus2 + - const: vcodec1_core + +required: + - compatible + - reg + - clocks + - clock-names + - dma-coherent + - interconnects + - interconnect-names + - interrupts + - iommus + - memory-region + - power-domains + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + video-codec@aa00000 { + compatible = "qcom,glymur-iris"; + reg = <0x0aa00000 0xf0000>; + + clocks = <&gcc_video_axi0_clk>, + <&videocc_mvs0c_clk>, + <&videocc_mvs0_clk>, + <&gcc_video_axi0c_clk>, + <&videocc_mvs0c_freerun_clk>, + <&videocc_mvs0_freerun_clk>, + <&gcc_video_axi1_clk>, + <&videocc_mvs1_clk>, + <&videocc_mvs1_freerun_clk>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "iface2", + "vcodec1_core", + "vcodec1_core_freerun"; + + dma-coherent; + + interconnects = <&hsc_noc_master_appss_proc &config_noc_slave_venus_cfg>, + <&mmss_noc_master_video &mc_virt_slave_ebi1>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1943 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x19e0 0x0>; + + iommu-map = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc_mvs0c_gdsc>, + <&videocc_mvs0_gdsc>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc_mvs1_gdsc>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vcodec1"; + + resets = <&gcc_video_axi0_clk_ares>, + <&gcc_video_axi0c_clk_ares>, + <&videocc_mvs0c_freerun_clk_ares>, + <&videocc_mvs0_freerun_clk_ares>, + <&gcc_video_axi1_clk_ares>, + <&videocc_mvs1_freerun_clk_ares>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core", + "bus2", + "vcodec1_core"; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000 366000000 549000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-533333334 { + opp-hz = /bits/ 64 <533333334 533333334 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-655000000 { + opp-hz = /bits/ 64 <655000000 655000000 982000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml index 59a3fde846d21..10716a93dd359 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml +++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml @@ -20,11 +20,11 @@ properties: clocks: minItems: 3 - maxItems: 7 + maxItems: 9 clock-names: minItems: 3 - maxItems: 7 + maxItems: 9 firmware-name: maxItems: 1 @@ -41,11 +41,11 @@ properties: power-domains: minItems: 1 - maxItems: 4 + maxItems: 5 power-domain-names: minItems: 1 - maxItems: 4 + maxItems: 5 required: - reg diff --git a/include/dt-bindings/media/qcom,glymur-iris.h b/include/dt-bindings/media/qcom,glymur-iris.h new file mode 100644 index 0000000000000..dcaa2bc21db56 --- /dev/null +++ b/include/dt-bindings/media/qcom,glymur-iris.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_GLYMUR_IRIS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_GLYMUR_IRIS_H_ + +#define IOMMU_FID_IRIS_FIRMWARE 0 + +#endif From b240294e3e9273d5438810d52db7fb59061e7f23 Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 15:38:03 +0530 Subject: [PATCH 0214/1058] PENDING: dt-bindings: media: qcom: venus: add iommu-map support Add optional iommu-map property to the Qualcomm Venus video codec binding to describe IOMMU stream IDs for additional functional blocks exposed by the hardware. Update the example to show how the firmware stream can be mapped to an SMMU stream ID using a function identifier. Signed-off-by: Renjiang Han --- .../devicetree/bindings/media/qcom,sc7180-venus.yaml | 5 +++++ include/dt-bindings/media/qcom,qcs615-venus.h | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 include/dt-bindings/media/qcom,qcs615-venus.h diff --git a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml index b21bed3148484..697cce56effaa 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml @@ -50,6 +50,9 @@ properties: iommus: maxItems: 1 + iommu-map: + maxItems: 1 + memory-region: maxItems: 1 @@ -116,6 +119,7 @@ unevaluatedProperties: false examples: - | #include + #include #include venus: video-codec@aa00000 { @@ -133,5 +137,6 @@ examples: clock-names = "core", "iface", "bus", "vcodec0_core", "vcodec0_bus"; iommus = <&apps_smmu 0x0c00 0x60>; + iommu-map = ; memory-region = <&venus_mem>; }; diff --git a/include/dt-bindings/media/qcom,qcs615-venus.h b/include/dt-bindings/media/qcom,qcs615-venus.h new file mode 100644 index 0000000000000..ca755f2f6aa40 --- /dev/null +++ b/include/dt-bindings/media/qcom,qcs615-venus.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ + +#define VENUS_FIRMWARE 0 + +#endif From b81da939ee34977039f3f2c24ffdf16544112969 Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 15:56:48 +0530 Subject: [PATCH 0215/1058] PENDING: media: qcom: venus: support PAS boot and flexible IOMMU handling On platforms where PAS is available, firmware authentication and reset are performed via the secure world, while IOMMU configuration may be handled either by Linux or outside of it. Extend the Venus firmware flow to support both PAS and non-PAS setups. When PAS is available, load the firmware using a PAS context and trigger the prepare/auth/reset sequence. If the firmware device is IOMMU-mapped, use its IOMMU domain to map the reserved firmware memory before reset; otherwise, retain the existing secure-world-managed behavior. When PAS is not available, fall back to the existing non-PAS firmware loading path where Linux performs firmware loading and IOMMU mapping. The firmware stream ID is described via the iommu-map function identifier in the device tree. Signed-off-by: Renjiang Han --- drivers/media/platform/qcom/venus/core.h | 2 + drivers/media/platform/qcom/venus/firmware.c | 294 ++++++++++++++----- 2 files changed, 217 insertions(+), 79 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 46705a6667762..a52cd14539183 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -223,6 +223,8 @@ struct venus_core { size_t mapped_mem_size; phys_addr_t mem_phys; size_t mem_size; + struct qcom_scm_pas_context *ctx; + bool iommu_domain_owned; } fw; struct mutex lock; struct list_head instances; diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 1de7436713ed9..dbfb322a99978 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "core.h" #include "firmware.h" @@ -78,87 +79,125 @@ int venus_set_hw_state(struct venus_core *core, bool resume) return 0; } -static int venus_load_fw(struct venus_core *core, const char *fwname, - phys_addr_t *mem_phys, size_t *mem_size) +static int venus_load_fw_prepare(struct venus_core *core, const char *fwname, + phys_addr_t *mem_phys, size_t *res_size, + const struct firmware **mdt) { - const struct firmware *mdt; struct resource res; - struct device *dev; ssize_t fw_size; - void *mem_va; int ret; - *mem_phys = 0; - *mem_size = 0; - - dev = core->dev; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res); if (ret) { - dev_err(dev, "failed to lookup reserved memory-region\n"); + dev_err(core->dev, "failed to lookup reserved memory-region\n"); return -EINVAL; } - ret = request_firmware(&mdt, fwname, dev); - if (ret < 0) + *mem_phys = res.start; + *res_size = resource_size(&res); + + ret = request_firmware(mdt, fwname, core->dev); + if (ret < 0) { + dev_err(core->dev, "%s: request_firmware: %d\n", __func__, ret); return ret; + } - fw_size = qcom_mdt_get_size(mdt); + fw_size = qcom_mdt_get_size(*mdt); if (fw_size < 0) { ret = fw_size; - goto err_release_fw; + goto err_release; } - *mem_phys = res.start; - *mem_size = resource_size(&res); - - if (*mem_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { + if (*res_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { ret = -EINVAL; - goto err_release_fw; - } - - mem_va = memremap(*mem_phys, *mem_size, MEMREMAP_WC); - if (!mem_va) { - dev_err(dev, "unable to map memory region %pa size %#zx\n", mem_phys, *mem_size); - ret = -ENOMEM; - goto err_release_fw; + goto err_release; } - if (core->use_tz) - ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, - mem_va, *mem_phys, *mem_size, NULL); - else - ret = qcom_mdt_load_no_init(dev, mdt, fwname, mem_va, - *mem_phys, *mem_size, NULL); + return 0; - memunmap(mem_va); -err_release_fw: - release_firmware(mdt); +err_release: + release_firmware(*mdt); return ret; } -static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, - size_t mem_size) +static int venus_load_fw(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) { - struct iommu_domain *iommu; + struct qcom_scm_pas_context *ctx; struct device *dev; int ret; - dev = core->fw.dev; - if (!dev) - return -EPROBE_DEFER; + dev = core->fw.dev ? core->fw.dev : core->dev; + ctx = devm_qcom_scm_pas_context_alloc(dev, VENUS_PAS_ID, mem_phys, res_size); + if (!ctx) { + dev_err(core->dev, "%s: ctx is null\n", __func__); + return -ENOMEM; + } - iommu = core->fw.iommu_domain; - core->fw.mapped_mem_size = mem_size; + ctx->use_tzmem = !!core->fw.dev; - ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, - IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + ret = qcom_mdt_pas_load(ctx, mdt, fwname, NULL); + qcom_scm_pas_metadata_release(ctx); if (ret) { - dev_err(dev, "could not map video firmware region\n"); + dev_err(core->dev, "%s: qcom_mdt_pas_load: %d\n", __func__, ret); return ret; } - venus_reset_cpu(core); + if (core->fw.iommu_domain) { + ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "%s: iommu_map: %d\n", __func__, ret); + return ret; + } + } + + core->fw.mapped_mem_size = res_size; + + ret = qcom_scm_pas_prepare_and_auth_reset(ctx); + if (ret) { + dev_err(core->dev, "%s: qcom_scm_pas_prepare_and_auth_reset: %d\n", __func__, ret); + if (core->fw.iommu_domain) + iommu_unmap(core->fw.iommu_domain, 0, res_size); + core->fw.mapped_mem_size = 0; + return ret; + } + core->fw.ctx = ctx; + return 0; +} + +static int venus_load_fw_no_tz(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) +{ + void *mem_va; + int ret; + + mem_va = memremap(mem_phys, res_size, MEMREMAP_WC); + if (!mem_va) { + dev_err(core->dev, + "unable to map memory region %pa size %#zx\n", &mem_phys, res_size); + return -ENOMEM; + } + + ret = qcom_mdt_load_no_init(core->fw.dev, mdt, fwname, mem_va, mem_phys, res_size, NULL); + memunmap(mem_va); + if (ret) { + dev_err(core->dev, "%s: qcom_mdt_load_no_init: %d\n", __func__, ret); + return ret; + } + + ret = iommu_map(core->fw.iommu_domain, VENUS_FW_START_ADDR, mem_phys, + res_size, IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "could not map video firmware region\n"); + return ret; + } + + core->fw.mapped_mem_size = res_size; + venus_reset_cpu(core); return 0; } @@ -212,36 +251,35 @@ int venus_boot(struct venus_core *core) { struct device *dev = core->dev; const struct venus_resources *res = core->res; + const struct firmware *mdt; const char *fwpath = NULL; phys_addr_t mem_phys; - size_t mem_size; + size_t res_size; int ret; if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || - (core->use_tz && !qcom_scm_is_available())) - return -EPROBE_DEFER; + (!core->use_tz && !core->fw.dev)) + return driver_deferred_probe_check_state(core->dev); - ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, - &fwpath); + ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, &fwpath); if (ret) fwpath = core->res->fwname; - ret = venus_load_fw(core, fwpath, &mem_phys, &mem_size); - if (ret) { - dev_err(dev, "fail to load video firmware\n"); - return -EINVAL; - } - - core->fw.mem_size = mem_size; - core->fw.mem_phys = mem_phys; + ret = venus_load_fw_prepare(core, fwpath, &mem_phys, &res_size, &mdt); + if (ret) + return ret; if (core->use_tz) - ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); + ret = venus_load_fw(core, mdt, fwpath, mem_phys, res_size); else - ret = venus_boot_no_tz(core, mem_phys, mem_size); + ret = venus_load_fw_no_tz(core, mdt, fwpath, mem_phys, res_size); - if (ret) + release_firmware(mdt); + + if (ret) { + dev_err(dev, "fail to load video firmware\n"); return ret; + } if (core->use_tz && res->cp_size) { /* @@ -259,24 +297,29 @@ int venus_boot(struct venus_core *core) res->cp_nonpixel_start, res->cp_nonpixel_size); if (ret) { - qcom_scm_pas_shutdown(VENUS_PAS_ID); - dev_err(dev, "set virtual address ranges fail (%d)\n", - ret); + venus_shutdown(core); + dev_err(dev, "set virtual address ranges fail (%d)\n", ret); return ret; } } - return 0; + return ret; } int venus_shutdown(struct venus_core *core) { int ret; - if (core->use_tz) + if (core->use_tz) { ret = qcom_scm_pas_shutdown(VENUS_PAS_ID); - else + if (core->fw.iommu_domain && core->fw.mapped_mem_size) { + iommu_unmap(core->fw.iommu_domain, 0, core->fw.mapped_mem_size); + core->fw.mapped_mem_size = 0; + } + core->fw.ctx = NULL; + } else { ret = venus_shutdown_no_tz(core); + } return ret; } @@ -301,6 +344,94 @@ int venus_firmware_check(struct venus_core *core) return -EINVAL; } +static struct device *venus_firmware_alloc_platform_dev(struct venus_core *core, + const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) { + dev_err(core->dev, "%s: platform_device_alloc err\n", __func__); + return ERR_PTR(-ENOMEM); + } + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + dev_err(core->dev, "%s: platform_device_add err(%d)\n", __func__, ret); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) { + dev_err(core->dev, "%s: of_dma_configure_id err(%d)\n", __func__, ret); + platform_device_unregister(to_platform_device(&pdev->dev)); + return ERR_PTR(ret); + } + + return &pdev->dev; +} + +static int venus_firmware_setup_iommu_dev(struct venus_core *core) +{ + const u32 f_id = VENUS_FIRMWARE; + struct device *dev; + int ret = 0; + + dev = venus_firmware_alloc_platform_dev(core, "video_firmware", &f_id); + if (IS_ERR(dev)) { + dev_err(core->dev, "%s: err\n", __func__); + return PTR_ERR(dev); + } + + if (!device_iommu_mapped(dev)) { + device_unregister(dev); + return -ENODEV; + } + + ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); + if (ret) { + device_unregister(dev); + return ret; + } + + core->fw.dev = dev; + core->fw.iommu_domain = iommu_get_domain_for_dev(core->fw.dev); + core->fw.iommu_domain_owned = false; + + return 0; +} + +static int venus_firmware_init_auto_detect(struct venus_core *core) +{ + int ret; + + core->use_tz = false; + if (qcom_scm_is_available()) { + if (qcom_scm_pas_supported(VENUS_PAS_ID)) + core->use_tz = true; + } else { + ret = driver_deferred_probe_check_state(core->dev); + if (ret == -EPROBE_DEFER) + return ret; + } + + /* + * 1. use_tz is false: No authentication is performed. + * 2. use_tz is true: TZ perform authentication. + * a. device_iommu_mapped true: Linux config smmu + * b. device_iommu_mapped false: TZ config smmu + */ + ret = venus_firmware_setup_iommu_dev(core); + if (ret == -ENODEV && core->use_tz) + ret = 0; + + return ret; +} + int venus_firmware_init(struct venus_core *core) { struct platform_device_info info; @@ -311,8 +442,8 @@ int venus_firmware_init(struct venus_core *core) np = of_get_child_by_name(core->dev->of_node, "video-firmware"); if (!np) { - core->use_tz = true; - return 0; + ret = venus_firmware_init_auto_detect(core); + return ret; } memset(&info, 0, sizeof(info)); @@ -351,6 +482,7 @@ int venus_firmware_init(struct venus_core *core) } core->fw.iommu_domain = iommu_dom; + core->fw.iommu_domain_owned = true; of_node_put(np); @@ -359,6 +491,7 @@ int venus_firmware_init(struct venus_core *core) err_iommu_free: iommu_domain_free(iommu_dom); err_unregister: + core->fw.dev = NULL; platform_device_unregister(pdev); of_node_put(np); return ret; @@ -371,14 +504,17 @@ void venus_firmware_deinit(struct venus_core *core) if (!core->fw.dev) return; - iommu = core->fw.iommu_domain; - - iommu_detach_device(iommu, core->fw.dev); + if (!core->use_tz && core->fw.iommu_domain_owned) { + iommu = core->fw.iommu_domain; - if (core->fw.iommu_domain) { - iommu_domain_free(iommu); - core->fw.iommu_domain = NULL; + if (iommu) { + iommu_detach_device(iommu, core->fw.dev); + iommu_domain_free(iommu); + } } - platform_device_unregister(to_platform_device(core->fw.dev)); + core->fw.dev = NULL; + core->fw.ctx = NULL; + core->fw.iommu_domain = NULL; + core->fw.iommu_domain_owned = false; } From 55580522e856b1f500493369d40cbe31f4db5f0e Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 10 Apr 2026 18:23:23 +0530 Subject: [PATCH 0216/1058] PENDING: dt-bindings: media: iris: add sm8550 iris context bank function IDs Add a dt-bindings header include/dt-bindings/media/qcom,sm8550-iris.h defining IRIS_NON_PIXEL_VCODEC (0) and IRIS_PIXEL (1) function IDs used to identify the non-pixel and pixel context bank SMMU stream mappings via iommu-map. Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Signed-off-by: Gourav Kumar --- include/dt-bindings/media/qcom,sm8550-iris.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 include/dt-bindings/media/qcom,sm8550-iris.h diff --git a/include/dt-bindings/media/qcom,sm8550-iris.h b/include/dt-bindings/media/qcom,sm8550-iris.h new file mode 100644 index 0000000000000..5165ef817f8bb --- /dev/null +++ b/include/dt-bindings/media/qcom,sm8550-iris.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ + +/* Function identifiers for iommu-map to attach for the context bank devices */ +#define IRIS_NON_PIXEL_VCODEC 0 +#define IRIS_PIXEL 1 + +#endif From 29dd374b66de864b7ee5bf4425a4309da94bfaef Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 7 Apr 2026 11:07:38 +0530 Subject: [PATCH 0217/1058] PENDING: media: iris: enable sm8550 context banks via init_cb_devs Wire up sm8550_init_cb_devs() in iris_platform_gen2.c to register the two child context-bank devices (iris_non_pixel and iris_pixel) using iris_create_cb_dev(), and hook it into the sm8550_data platform data via the .init_cb_devs callback. Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- .../platform/qcom/iris/iris_platform_vpu3x.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 8763a78381c2e..ffa5aa018c1bb 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -104,6 +104,47 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = { }, }; +static int sm8550_init_cb_devs(struct iris_core *core) +{ + const u32 f_id_np = 0; /* IRIS_NON_PIXEL_VCODEC */ + const u32 f_id_p = 1; /* IRIS_PIXEL */ + struct device *dev; + + dev = iris_create_cb_dev(core, "iris_non_pixel", &f_id_np); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + core->dev_np = dev; + core->dev_bs = core->dev_np; + + dev = iris_create_cb_dev(core, "iris_pixel", &f_id_p); + if (IS_ERR(dev)) + goto err_unreg_dev_np; + + core->dev_p = dev; + + return 0; + +err_unreg_dev_np: + platform_device_unregister(to_platform_device(core->dev_np)); + core->dev_np = NULL; + core->dev_bs = NULL; + + return PTR_ERR(dev); +} + +static void sm8550_deinit_cb_devs(struct iris_core *core) +{ + if (core->dev_np) + platform_device_unregister(to_platform_device(core->dev_np)); + if (core->dev_p) + platform_device_unregister(to_platform_device(core->dev_p)); + + core->dev_np = NULL; + core->dev_bs = NULL; + core->dev_p = NULL; +} + /* * Shares most of SM8550 data except: * - inst_caps to platform_inst_cap_qcs8300 @@ -141,6 +182,8 @@ const struct iris_platform_data qcs8300_data = { const struct iris_platform_data sm8550_data = { .firmware_desc_gen2 = &iris_vpu30_p4_gen2_desc, .vpu_ops = &iris_vpu3_ops, + .init_cb_devs = sm8550_init_cb_devs, + .deinit_cb_devs = sm8550_deinit_cb_devs, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), .clk_rst_tbl = sm8550_clk_reset_table, From bf3e42b8c7871271a0b0cb8272948155cccf1a0c Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Fri, 13 Mar 2026 18:49:38 +0530 Subject: [PATCH 0218/1058] PENDING: media: iris: add context bank devices using iommu-map Different stream IDs from VPU would be associated to one of these CB. Multiple CBs are needed to increase the IOVA for the video usecases like higher concurrent sessions. Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/iris/iris_core.h | 6 ++++ .../platform/qcom/iris/iris_platform_common.h | 3 ++ drivers/media/platform/qcom/iris/iris_probe.c | 31 ++++++++++++++--- .../media/platform/qcom/iris/iris_resources.c | 34 +++++++++++++++++++ .../media/platform/qcom/iris/iris_resources.h | 1 + 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index e668d5c262167..9f5c9e59eff0e 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -41,6 +41,9 @@ enum iris_vcodec_core_id { * struct iris_core - holds core parameters valid for all instances * * @dev: reference to device structure + * @dev_np: reference to non-pixel context bank device structure + * @dev_p: reference to pixel context bank device structure + * @dev_bs: reference to bitstream context bank device structure * @reg_base: IO memory base address * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure @@ -86,6 +89,9 @@ enum iris_vcodec_core_id { struct iris_core { struct device *dev; + struct device *dev_np; + struct device *dev_p; + struct device *dev_bs; void __iomem *reg_base; int irq; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 5e38b48bd502b..58651f0725b8a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -314,6 +314,9 @@ struct iris_platform_data { const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2; const struct vpu_ops *vpu_ops; + + int (*init_cb_devs)(struct iris_core *core); + void (*deinit_cb_devs)(struct iris_core *core); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; const struct bw_info *bw_tbl_dec; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 3813cf48028e1..278f6df716e82 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -131,6 +131,20 @@ static int iris_init_resets(struct iris_core *core) core->iris_platform_data->controller_rst_tbl_size); } +static int iris_init_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->init_cb_devs) + return core->iris_platform_data->init_cb_devs(core); + + return 0; +} + +static void iris_deinit_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->deinit_cb_devs) + core->iris_platform_data->deinit_cb_devs(core); +} + static int iris_init_resources(struct iris_core *core) { int ret; @@ -201,6 +215,7 @@ static void iris_remove(struct platform_device *pdev) return; iris_core_deinit(core); + iris_deinit_cb_devs(core); video_unregister_device(core->vdev_dec); video_unregister_device(core->vdev_enc); @@ -269,10 +284,14 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - ret = v4l2_device_register(dev, &core->v4l2_dev); + ret = iris_init_cb_devs(core); if (ret) return ret; + ret = v4l2_device_register(dev, &core->v4l2_dev); + if (ret) + goto err_deinit_cb; + ret = iris_register_video_device(core, DECODER); if (ret) goto err_v4l2_unreg; @@ -285,9 +304,11 @@ static int iris_probe(struct platform_device *pdev) dma_mask = core->iris_platform_data->dma_mask; - ret = dma_set_mask_and_coherent(dev, dma_mask); - if (ret) - goto err_vdev_unreg_enc; + if (device_iommu_mapped(core->dev)) { + ret = dma_set_mask_and_coherent(core->dev, dma_mask); + if (ret) + goto err_vdev_unreg_enc; + } dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); @@ -306,6 +327,8 @@ static int iris_probe(struct platform_device *pdev) video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); +err_deinit_cb: + iris_deinit_cb_devs(core); return ret; } diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 129cb9a481372..2a93e42596674 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -183,3 +184,36 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type return 0; } + +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) + return ERR_PTR(-ENOMEM); + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) + goto error_unregister; + + ret = dma_set_mask_and_coherent(&pdev->dev, core->iris_platform_data->dma_mask); + if (ret) + goto error_unregister; + + return &pdev->dev; + +error_unregister: + platform_device_unregister(to_platform_device(&pdev->dev)); + + return ERR_PTR(ret); +} diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index d5692e4694b14..3c7246c3057ae 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -17,5 +17,6 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, bool hwmode); +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id); #endif From cd24d3cb362ea76b7459fd10495017637bcb0bdf Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Fri, 13 Mar 2026 18:49:39 +0530 Subject: [PATCH 0219/1058] PENDING: media: iris: add helper to select context bank device Depending on the buffer type (input, output and internal), associated context bank is selected, if available. Fallback to parent device for backward compatibility. Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- .../media/platform/qcom/iris/iris_buffer.c | 8 ++-- .../media/platform/qcom/iris/iris_hfi_queue.c | 16 +++---- .../media/platform/qcom/iris/iris_resources.c | 42 +++++++++++++++++++ .../media/platform/qcom/iris/iris_resources.h | 1 + drivers/media/platform/qcom/iris/iris_vidc.c | 4 +- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 246ad0abbac35..249c9f1d0d5da 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -529,7 +529,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, enum iris_buffer_type buffer_type, u32 index) { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer_type); struct iris_buffer *buffer; if (!buffers->size) @@ -545,7 +545,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, buffer->buffer_size = buffers->size; buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; - buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, + buffer->kvaddr = dma_alloc_attrs(dev, buffer->buffer_size, &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); if (!buffer->kvaddr) { kfree(buffer); @@ -682,10 +682,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) { - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer->type); list_del(&buffer->list); - dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + dma_free_attrs(dev, buffer->buffer_size, buffer->kvaddr, buffer->device_addr, buffer->dma_attrs); kfree(buffer); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index bf6db23b53e21..f465ff00a9ba3 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -245,25 +245,26 @@ static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) int iris_hfi_queues_init(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; struct iris_hfi_queue_table_header *q_tbl_hdr; u32 queue_size; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); - core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, + core->iface_q_table_vaddr = dma_alloc_attrs(dev, queue_size, &core->iface_q_table_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->iface_q_table_vaddr) { - dev_err(core->dev, "queues alloc and map failed\n"); + dev_err(dev, "queues alloc and map failed\n"); return -ENOMEM; } - core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, + core->sfr_vaddr = dma_alloc_attrs(dev, SFR_SIZE, &core->sfr_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->sfr_vaddr) { - dev_err(core->dev, "sfr alloc and map failed\n"); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dev_err(dev, "sfr alloc and map failed\n"); + dma_free_attrs(dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); return -ENOMEM; } @@ -291,6 +292,7 @@ int iris_hfi_queues_init(struct iris_core *core) void iris_hfi_queues_deinit(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; u32 queue_size; if (!core->iface_q_table_vaddr) @@ -300,7 +302,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) iris_hfi_queue_deinit(&core->message_queue); iris_hfi_queue_deinit(&core->command_queue); - dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, + dma_free_attrs(dev, SFR_SIZE, core->sfr_vaddr, core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); core->sfr_vaddr = NULL; @@ -309,7 +311,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); core->iface_q_table_vaddr = NULL; diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 2a93e42596674..df9b7badf0c62 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -13,6 +13,7 @@ #include #include "iris_core.h" +#include "iris_instance.h" #include "iris_resources.h" #define BW_THRESHOLD 50000 @@ -217,3 +218,44 @@ struct device *iris_create_cb_dev(struct iris_core *core, const char *name, cons return ERR_PTR(ret); } + +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_core *core = inst->core; + struct device *dev = NULL; + + switch (buffer_type) { + case BUF_INPUT: + if (inst->domain == DECODER) + dev = core->dev_bs; + else + dev = core->dev_p; + break; + case BUF_OUTPUT: + if (inst->domain == DECODER) + dev = core->dev_p; + else + dev = core->dev_bs; + break; + case BUF_BIN: + dev = core->dev_bs; + break; + case BUF_DPB: + case BUF_PARTIAL: + case BUF_SCRATCH_2: + case BUF_VPSS: + dev = core->dev_p; + break; + case BUF_ARP: + case BUF_COMV: + case BUF_LINE: + case BUF_NON_COMV: + case BUF_PERSIST: + dev = core->dev_np; + break; + default: + dev_err(core->dev, "invalid buffer type: %d\n", buffer_type); + } + + return dev ? dev : core->dev; +} diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index 3c7246c3057ae..982ca764cb20b 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -18,5 +18,6 @@ int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, bool hwmode); struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id); +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 19d4db07d3bca..ae27d12a06b14 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -112,7 +112,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ src_vq->drv_priv = inst; src_vq->buf_struct_size = sizeof(struct iris_buffer); src_vq->min_reqbufs_allocation = MIN_BUFFERS; - src_vq->dev = inst->core->dev; + src_vq->dev = iris_get_cb_dev(inst, BUF_INPUT); src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) @@ -126,7 +126,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ dst_vq->drv_priv = inst; dst_vq->buf_struct_size = sizeof(struct iris_buffer); dst_vq->min_reqbufs_allocation = MIN_BUFFERS; - dst_vq->dev = inst->core->dev; + dst_vq->dev = iris_get_cb_dev(inst, BUF_OUTPUT); dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); From c4982a41dac0918a6b93b49a72e01d7c60ea1965 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 11 Feb 2026 12:19:16 +0530 Subject: [PATCH 0220/1058] FROMLIST: media: iris: Enable Secure PAS support with IOMMU managed by Linux Most Qualcomm platforms feature a inhouse hypervisor (such as Gunyah or QHEE), which typically handles IOMMU configuration. This includes mapping memory regions and device memory resources for remote processors by intercepting qcom_scm_pas_auth_and_reset() calls. These mappings are later removed during teardown. Additionally, SHM bridge setup is required to enable memory protection for both remoteproc metadata and its memory regions. When the hypervisor is absent, the operating system must perform these configurations instead. Support for handling IOMMU and SHM setup in the absence of a hypervisor is now in place. Extend the Iris driver to enable this functionality on platforms where IOMMU is managed by Linux (i.e., non-Gunyah, non-QHEE). Additionally, the Iris driver must map the firmware and its required resources to the firmware SID, which is now specified via the device tree. Link: https://lore.kernel.org/lkml/20250819165447.4149674-12-mukesh.ojha@oss.qualcomm.com/ Signed-off-by: Vikash Garodia Signed-off-by: Mukesh Ojha --- drivers/media/platform/qcom/iris/iris_core.c | 9 +- drivers/media/platform/qcom/iris/iris_core.h | 5 + .../media/platform/qcom/iris/iris_firmware.c | 127 ++++++++++++++++-- .../media/platform/qcom/iris/iris_firmware.h | 2 + 4 files changed, 133 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index bd22076f35576..b65ede5bd693a 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -18,6 +18,7 @@ void iris_core_deinit(struct iris_core *core) if (core->state != IRIS_CORE_DEINIT) { iris_fw_unload(core); iris_vpu_power_off(core); + iris_fw_deinit(core); iris_hfi_queues_deinit(core); core->state = IRIS_CORE_DEINIT; } @@ -67,10 +68,14 @@ int iris_core_init(struct iris_core *core) if (ret) goto error_queue_deinit; - ret = iris_fw_load(core); + ret = iris_fw_init(core); if (ret) goto error_power_off; + ret = iris_fw_load(core); + if (ret) + goto error_firmware_deinit; + ret = iris_vpu_boot_firmware(core); if (ret) goto error_unload_fw; @@ -94,6 +99,8 @@ int iris_core_init(struct iris_core *core) error_unload_fw: iris_fw_unload(core); +error_firmware_deinit: + iris_fw_deinit(core); error_power_off: iris_vpu_power_off(core); error_queue_deinit: diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 9f5c9e59eff0e..1bc001df0cec4 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -97,6 +97,11 @@ struct iris_core { struct v4l2_device v4l2_dev; struct video_device *vdev_dec; struct video_device *vdev_enc; + struct video_firmware { + struct device *dev; + struct qcom_scm_pas_context *ctx; + struct iommu_domain *iommu_domain; + } fw; const struct v4l2_file_operations *iris_v4l2_file_ops; const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec; const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc; diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index 64a2170bf538a..b2f13dda31b0c 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -3,10 +3,15 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include +#include +#include #include +#include #include +#include #include #include "iris_core.h" @@ -96,6 +101,7 @@ static const struct firmware *iris_detect_firmware(struct iris_core *core, static int iris_load_fw_to_memory(struct iris_core *core) { const struct firmware *firmware = NULL; + struct qcom_scm_pas_context *ctx; struct device *dev = core->dev; struct resource res; phys_addr_t mem_phys; @@ -112,6 +118,14 @@ static int iris_load_fw_to_memory(struct iris_core *core) mem_phys = res.start; res_size = resource_size(&res); + dev = core->fw.dev ? : core->dev; + + ctx = devm_qcom_scm_pas_context_alloc(dev, IRIS_PAS_ID, mem_phys, res_size); + if (!ctx) + return -ENOMEM; + + ctx->use_tzmem = core->fw.dev; + firmware = iris_detect_firmware(core, &fw_name); if (IS_ERR(firmware)) return PTR_ERR(firmware); @@ -130,9 +144,29 @@ static int iris_load_fw_to_memory(struct iris_core *core) goto err_release_fw; } - ret = qcom_mdt_load(dev, firmware, fw_name, - IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL); + ret = qcom_mdt_pas_load(ctx, firmware, fw_name, mem_virt, NULL); + qcom_scm_pas_metadata_release(ctx); + if (ret) + goto err_mem_unmap; + + if (core->fw.iommu_domain) { + ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) + goto err_mem_unmap; + } + + ret = qcom_scm_pas_prepare_and_auth_reset(ctx); + if (ret) + goto err_iommu_unmap; + + core->fw.ctx = ctx; + return ret; + +err_iommu_unmap: + iommu_unmap(core->fw.iommu_domain, 0, res_size); +err_mem_unmap: memunmap(mem_virt); err_release_fw: release_firmware(firmware); @@ -151,12 +185,6 @@ int iris_fw_load(struct iris_core *core) return ret; } - ret = qcom_scm_pas_auth_and_reset(IRIS_PAS_ID); - if (ret) { - dev_err(core->dev, "auth and reset failed: %d\n", ret); - return ret; - } - for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) { cp_config = &core->iris_platform_data->tz_cp_config_data[i]; ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, @@ -175,10 +203,91 @@ int iris_fw_load(struct iris_core *core) int iris_fw_unload(struct iris_core *core) { - return qcom_scm_pas_shutdown(IRIS_PAS_ID); + struct qcom_scm_pas_context *ctx = core->fw.ctx; + int ret; + + if (!ctx) + return -EINVAL; + + ret = qcom_scm_pas_shutdown(ctx->pas_id); + if (core->fw.iommu_domain) + iommu_unmap(core->fw.iommu_domain, 0, ctx->mem_size); + + core->fw.ctx = NULL; + return ret; } int iris_set_hw_state(struct iris_core *core, bool resume) { return qcom_scm_set_remote_state(resume, 0); } + +int iris_fw_init(struct iris_core *core) +{ + struct platform_device_info info; + struct iommu_domain *iommu_dom; + struct platform_device *pdev; + struct device_node *np; + int ret; + + np = of_get_child_by_name(core->dev->of_node, "video-firmware"); + if (!np) + return 0; + + memset(&info, 0, sizeof(info)); + info.fwnode = &np->fwnode; + info.parent = core->dev; + info.name = np->name; + info.dma_mask = DMA_BIT_MASK(32); + + pdev = platform_device_register_full(&info); + if (IS_ERR(pdev)) { + of_node_put(np); + return PTR_ERR(pdev); + } + + pdev->dev.of_node = np; + + ret = of_dma_configure(&pdev->dev, np, true); + if (ret) + goto err_unregister; + + core->fw.dev = &pdev->dev; + + iommu_dom = iommu_get_domain_for_dev(core->fw.dev); + if (!iommu_dom) { + ret = -EINVAL; + goto err_unset_fw_dev; + } + + ret = iommu_attach_device(iommu_dom, core->fw.dev); + if (ret) + goto err_unset_fw_dev; + + core->fw.iommu_domain = iommu_dom; + + of_node_put(np); + + return 0; + +err_unset_fw_dev: + core->fw.dev = NULL; +err_unregister: + platform_device_unregister(pdev); + of_node_put(np); + return ret; +} + +void iris_fw_deinit(struct iris_core *core) +{ + if (!core->fw.dev) + return; + + if (core->fw.iommu_domain) { + iommu_detach_device(core->fw.iommu_domain, core->fw.dev); + core->fw.iommu_domain = NULL; + } + + platform_device_unregister(to_platform_device(core->fw.dev)); + core->fw.dev = NULL; +} diff --git a/drivers/media/platform/qcom/iris/iris_firmware.h b/drivers/media/platform/qcom/iris/iris_firmware.h index e833ecd348871..adde461099667 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.h +++ b/drivers/media/platform/qcom/iris/iris_firmware.h @@ -11,5 +11,7 @@ struct iris_core; int iris_fw_load(struct iris_core *core); int iris_fw_unload(struct iris_core *core); int iris_set_hw_state(struct iris_core *core, bool resume); +int iris_fw_init(struct iris_core *core); +void iris_fw_deinit(struct iris_core *core); #endif From dc89f72844c066088e5d47e5efa9e32589b2959d Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Thu, 2 Apr 2026 11:44:12 +0530 Subject: [PATCH 0221/1058] PENDING: media: iris: update MDT PAS load call for new API The Qualcomm MDT loader changed qcom_mdt_pas_load() to take only four arguments and use the PAS context for relocation and memory handling. Update the iris firmware loading path to match that interface by dropping the temporary memremap/memunmap flow, removing the extra mem_virt argument from qcom_mdt_pas_load(), and simplifying the error path accordingly. This keeps the iris driver aligned with the SCM/PAS loader changes and fixes the build failure caused by the old five-argument call. Signed-off-by: Gourav Kumar --- drivers/media/platform/qcom/iris/iris_firmware.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index b2f13dda31b0c..64c5ad4b4fc21 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -108,7 +108,6 @@ static int iris_load_fw_to_memory(struct iris_core *core) const char *fw_name; size_t res_size; ssize_t fw_size; - void *mem_virt; int ret; ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); @@ -138,22 +137,16 @@ static int iris_load_fw_to_memory(struct iris_core *core) goto err_release_fw; } - mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); - if (!mem_virt) { - ret = -ENOMEM; - goto err_release_fw; - } - - ret = qcom_mdt_pas_load(ctx, firmware, fw_name, mem_virt, NULL); + ret = qcom_mdt_pas_load(ctx, firmware, fw_name, NULL); qcom_scm_pas_metadata_release(ctx); if (ret) - goto err_mem_unmap; + goto err_release_fw; if (core->fw.iommu_domain) { ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); if (ret) - goto err_mem_unmap; + goto err_release_fw; } ret = qcom_scm_pas_prepare_and_auth_reset(ctx); @@ -166,8 +159,6 @@ static int iris_load_fw_to_memory(struct iris_core *core) err_iommu_unmap: iommu_unmap(core->fw.iommu_domain, 0, res_size); -err_mem_unmap: - memunmap(mem_virt); err_release_fw: release_firmware(firmware); From 85b29c05f8142d6745c6d57d40f3b937128d1751 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 18 Dec 2025 00:09:52 -0800 Subject: [PATCH 0222/1058] FROMLIST: arm64: dts: qcom: hamoa: Add CoreSight nodes for APSS debug block The APSS debug block is built with CoreSight devices like ETM, replicator, funnel and TMC ETF. Add dt nodes for these devices to enable ETM trace. Link: https://lore.kernel.org/all/20251218-cpu_cluster_component_pm-v2-12-2335a6ae62a0@oss.qualcomm.com/ Signed-off-by: Jie Gan Co-developed-by: Yuanfang Zhang Signed-off-by: Yuanfang Zhang --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 926 ++++++++++++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa.dtsi | 12 + 2 files changed, 938 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 4ba751a65142b..5479b00faafe6 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -317,6 +317,210 @@ }; }; + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + etm8: etm-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + etm9: etm-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + etm10: etm-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + etm11: etm-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-x1e80100", "qcom,scm"; @@ -6955,6 +7159,14 @@ }; }; + port@4 { + reg = <4>; + + funnel1_in4: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + port@5 { reg = <5>; @@ -8245,6 +8457,720 @@ }; }; + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&funnel1_in4>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + funnel@134d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + funnel@13901000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13901000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13909000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13909000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + replicator@13990000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13990000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@139a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@139b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; + }; + }; + }; + }; + + replicator@139c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; + }; + }; + }; + }; + + funnel@139d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x139d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + cluster2_funnel_l2: funnel@13e01000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13e01000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; + }; + }; + }; + }; + + cluster2_etf: tmc@13e09000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13e09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_0: replicator@13e90000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13e90000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; + + out-ports { + port { + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; + }; + }; + }; + }; + + cluster2_rep_2_1: replicator@13ea0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13ea0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; + }; + }; + }; + }; + + cluster2_rep_2_2: replicator@13eb0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13eb0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_3: replicator@13ec0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13ec0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; + + out-ports { + port { + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; + }; + }; + }; + }; + + cluster2_funnel_l1: funnel@13ed0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13ed0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; + }; + }; + }; + }; + apps_smmu: iommu@15000000 { compatible = "qcom,x1e80100-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0 0x15000000 0 0x100000>; diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 9ab4f26b35f29..70790e8fc4925 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -35,6 +35,18 @@ /delete-node/ &thermal_gpuss_5; /delete-node/ &thermal_gpuss_6; /delete-node/ &thermal_gpuss_7; +/delete-node/ &etm8; +/delete-node/ &etm9; +/delete-node/ &etm10; +/delete-node/ &etm11; +/delete-node/ &cluster2_funnel_l1; +/delete-node/ &cluster2_funnel_l2; +/delete-node/ &cluster2_etf; +/delete-node/ &cluster2_rep_2_0; +/delete-node/ &cluster2_rep_2_1; +/delete-node/ &cluster2_rep_2_2; +/delete-node/ &cluster2_rep_2_3; +/delete-node/ &apss_funnel_in2; &gcc { compatible = "qcom,x1p42100-gcc", "qcom,x1e80100-gcc"; From 4b987d8a4f8ae44c41f892d2ed0622159e8ff4e5 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 4 Feb 2026 10:22:02 +0800 Subject: [PATCH 0223/1058] FROMLIST: arm64: dts: qcom: hamoa: enable ETR and CTCU devices Embedded Trace Router(ETR) is working as a DDR memory sink to collect tracing data from source device. The CTCU serves as the control unit for the ETR device, managing its behavior to determine how trace data is collected. Link: https://lore.kernel.org/all/20260204-enable-ctcu-and-etr-v3-2-0bb95c590ae1@oss.qualcomm.com/ Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 160 +++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 5479b00faafe6..228910bfc49d8 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -7008,6 +7008,35 @@ }; }; + ctcu@10001000 { + compatible = "qcom,x1e80100-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + stm@10002000 { compatible = "arm,coresight-stm", "arm,primecell"; reg = <0x0 0x10002000 0x0 0x1000>, @@ -7230,6 +7259,122 @@ }; }; + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc_etr: tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu 0x04e0 0x0>; + + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu 0x0500 0x0>; + + arm,scatter-gather; + arm,buffer-size = <0x400000>; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tpdm@10800000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x10800000 0x0 0x1000>; @@ -7543,7 +7688,20 @@ }; out-ports { - port { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + + port@1 { + reg = <1>; + swao_rep_out1: endpoint { remote-endpoint = <&eud_in>; }; From 33d61dc0007aed5c148ac72e553ef1b48ebbb999 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 9 Apr 2026 14:51:08 +0530 Subject: [PATCH 0224/1058] FROMLIST: arm64: dts: qcom: x1e80100: Add CAMCC block definition Add the CAMCC block for x1e80100. The x1e80100 CAMCC block is an iteration of previous CAMCC blocks with the exception of having two required power-domains not just one. And update the compatible for camcc and videocc nodes on Purwa to match with their respective Purwa (X1P42100) specific drivers. https://lore.kernel.org/all/20260409-purwa-videocc-camcc-v4-6-5a8e5f2dd4b2@oss.qualcomm.com/ Reviewed-by: Vladimir Zapolskiy Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Bryan O'Donoghue Signed-off-by: Jagadeesh Kona --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 17 +++++++++++++++++ arch/arm64/boot/dts/qcom/purwa.dtsi | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 228910bfc49d8..6cafe561e4ce5 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -5754,6 +5755,22 @@ #power-domain-cells = <1>; }; + camcc: clock-controller@ade0000 { + compatible = "qcom,x1e80100-camcc"; + reg = <0 0x0ade0000 0 0x20000>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>; + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,x1e80100-mdss"; reg = <0 0x0ae00000 0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 70790e8fc4925..81007578a7088 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -6,6 +6,8 @@ /* X1P42100 is heavily based on hamoa, with some meaningful differences */ #include "hamoa.dtsi" +#include + /delete-node/ &bwmon_cluster0; /delete-node/ &cluster_pd2; /delete-node/ &cpu_map_cluster2; @@ -48,10 +50,18 @@ /delete-node/ &cluster2_rep_2_3; /delete-node/ &apss_funnel_in2; +&camcc { + compatible = "qcom,x1p42100-camcc"; +}; + &gcc { compatible = "qcom,x1p42100-gcc", "qcom,x1e80100-gcc"; }; +&videocc { + compatible = "qcom,x1p42100-videocc"; +}; + &gmu { compatible = "qcom,adreno-gmu-x145.0", "qcom,adreno-gmu"; }; From e1f631fdf723484b9c1abcc57f19ab6534501fa4 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 25 Feb 2026 21:41:13 -0800 Subject: [PATCH 0225/1058] FROMLIST: arm64: dts: qcom: hamoa: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Signed-off-by: Xin Liu Link: https://lore.kernel.org/all/20260226054113.4156874-1-xin.liu@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 6cafe561e4ce5..79f24ba282ed2 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -667,6 +667,11 @@ #power-domain-cells = <0>; /* TODO: system-wide idle states */ }; + + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; }; reserved-memory { From eb9c315330aad893146003bcb4eafff7463adcb3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:39 +0000 Subject: [PATCH 0226/1058] FROMLIST: arm64: dts: qcom: x1e80100: Add CCI definitions Add in two CCI buses. One bus has two CCI bus master pinouts: cci_i2c_sda0 = gpio101 cci_i2c_scl0 = gpio102 cci_i2c_sda1 = gpio103 cci_i2c_scl1 = gpio104 The second bus has two CCI bus master pinouts: cci_i2c_sda2 = gpio105 cci_i2c_scl2 = gpio106 aon_cci_i2c_sda3 = gpio235 aon_cci_i2c_scl3 = gpio236 Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-2-1d5a9306116a@linaro.org/ Reviewed-by: Konrad Dybcio Reviewed-by: Vladimir Zapolskiy Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 79f24ba282ed2..5c69a0bea9897 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5760,6 +5760,84 @@ #power-domain-cells = <1>; }; + cci0: cci@ac15000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci0_default>; + pinctrl-1 = <&cci0_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci1_default>; + pinctrl-1 = <&cci1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; @@ -6357,6 +6435,78 @@ gpio-ranges = <&tlmm 0 0 239>; wakeup-parent = <&pdc>; + cci0_default: cci0-default-state { + cci0_i2c0_default: cci0-i2c0-default-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_i2c1_default: cci0-i2c1-default-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_sleep: cci0-sleep-state { + cci0_i2c0_sleep: cci0-i2c0-sleep-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci0_i2c1_sleep: cci0-i2c1-sleep-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_default: cci1-default-state { + cci1_i2c0_default: cci1-i2c0-default-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_i2c1_default: cci1-i2c1-default-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_sleep: cci1-sleep-state { + cci1_i2c0_sleep: cci1-i2c0-sleep-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_i2c1_sleep: cci1-i2c1-sleep-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-down; + }; + }; + edp0_hpd_default: edp0-hpd-default-state { pins = "gpio119"; function = "edp0_hot"; From 2a31c5a444fe6c9f72a01dccfe81a2b13eb905ed Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:40 +0000 Subject: [PATCH 0227/1058] FROMLIST: arm64: dts: qcom: x1e80100: Add CAMSS block definition Add dtsi to describe the xe180100 CAMSS block 4 x CSIPHY 3 x TPG 2 x CSID 2 x CSID Lite 2 x IFE 2 x IFE Lite Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-3-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 348 ++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 5c69a0bea9897..04f96f88d6965 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -5838,6 +5840,352 @@ }; }; + camss: isp@acb7000 { + compatible = "qcom,x1e80100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0ace6000 0 0x1000>, + <0 0x0ace8000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0ac71000 0 0xf000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + phys = <&csiphy0 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy1 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy2 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + phy-names = "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4"; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy1_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy2_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; + }; + }; + }; + + csiphy0: phy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace4000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy1: phy@ace6000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace6000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy2: phy@ace8000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace8000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy4: phy@acec000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0acec000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxa_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + csiphy_mxa_opp_table: opp-table-mxa { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; From 3dc9365aa3fb70dd7c9385786ddf67af16038d59 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:41 +0000 Subject: [PATCH 0228/1058] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add pm8010 CRD pmic,id=m regulators Add pmic,id = m rpmh to regulator definitions. This regulator set provides vreg_l3m_1p8 the regulator for the ov08x40 RGB sensor on the CRD. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-4-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index a9c5c523575ee..7b9a40a7b9a95 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -897,6 +897,36 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From b508ca0f71a4dff04ceafc15cab185aec208f5fd Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:42 +0000 Subject: [PATCH 0229/1058] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add ov08x40 RGB sensor on CSIPHY4 Define ov08x40 on cci1_i2c1. The RGB sensor appears on the AON CCI pins connected to CSIPHY4 in four lane mode. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-5-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 7b9a40a7b9a95..3f62ec0241691 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -933,6 +934,65 @@ status = "okay"; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&ov08x40_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov08x40"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam_rgb_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov08x40_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1553,6 +1613,22 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 85a2be0808172d27e15855c909a5e41d9b88c87a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:43 +0000 Subject: [PATCH 0230/1058] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add the PM8010 PMIC providing the following voltage rails: vreg_l1m_r @ 1v2 IR sensor vreg_l2m_r @ 1v2 RGB sensor vreg_l3m_r @ 1v8 IR sensor vreg_l4m_r @ 1v8 RGB sensor vreg_l5m_r @ 2v8 IR sensor vreg_l7m_r @ 2v8 RGB sensor Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-6-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 5d49df41be02a..70e50ccf67677 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -562,6 +562,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -805,6 +812,58 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; + }; &gpu { From ebba392d34325ebb45e199da5ff007e29ffc2329 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:44 +0000 Subject: [PATCH 0231/1058] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add on ov02c10 RGB sensor on CSIPHY4 Switch on the ov02c10 RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-7-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 70e50ccf67677..8ca7294187dfe 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -866,6 +867,66 @@ }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7m_2p8>; + dvdd-supply = <&vreg_l2m_1p2>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &gpu { status = "okay"; }; @@ -1447,6 +1508,22 @@ <72 2>, /* Secure EC I2C connection (?) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From 9bb6c3a1cf198f94b0657c9a95e3d0cb38bd9f61 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:45 +0000 Subject: [PATCH 0232/1058] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add voltage regulators-8 for Camera on slim7x including: - vreg_l1m_1p2 - vreg_l3m_1p8 Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-8-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index beb1475d7fa0c..0a8275d501f85 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -795,6 +795,57 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From 0cf54e1a3c5962905e69f6953592bbfb85b5b3d1 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:46 +0000 Subject: [PATCH 0233/1058] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add l7b_2p8 voltage regulator for RGB camera Some sleuthing work by Aleksandrs Vinarskis in the bowels of the ACPI tables for this part shows we need l7b_2p8 for the avdd supply. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-9-1d5a9306116a@linaro.org/ Suggested-by: Aleksandrs Vinarskis Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index 0a8275d501f85..bcf3e2f610e66 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -552,6 +552,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; From 521d77887a09f94b66d6f9d5173a422ef5b92868 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:47 +0000 Subject: [PATCH 0234/1058] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add ov02c10 RGB sensor on CSIPHY4 Add in the RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-10-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index bcf3e2f610e66..06300d21223fb 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -7,6 +7,7 @@ #include #include +#include #include #include "hamoa.dtsi" @@ -863,6 +864,66 @@ firmware-name = "qcom/x1e80100/LENOVO/83ED/qcdxkmsuc8380.mbn"; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l1m_1p2>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1410,6 +1471,22 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From a50636aee0bc4fbb5ee4f483d3ac8df94e435a90 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:48 +0000 Subject: [PATCH 0235/1058] FROMLIST: arm64: dts: qcom: x1e80100-dell-inspiron14-7441: Switch on CAMSS RGB sensor Inspiron14 has a ov02e10 sensor on CSIPHY4. Enable the list of dependencies now. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-11-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi index db291730130c7..58d390fe3af88 100644 --- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "hamoa-pmics.dtsi" @@ -792,6 +793,66 @@ }; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02e10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@10 { + compatible = "ovti,ov02e10"; + reg = <0x10>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_cam_1p8>; + + port { + ov02e10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <360000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; From 175075f054e7c52d0023a5ac02973ec82308a974 Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Fri, 27 Feb 2026 13:29:39 +0800 Subject: [PATCH 0236/1058] FROMLIST: arm64: dts: qcom: hamoa-iot-som: Add pm8010 L4M regulator Add pm8010 L4M regulator which is used by Camera I2C pull-up. Signed-off-by: Tingguo Cheng Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260227-hamoa_evk-v1-1-36f895a24d8f@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi index 9c5e77df00547..92c7d97d2b99f 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi @@ -376,6 +376,21 @@ regulator-initial-mode = ; }; }; + + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vrer_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + }; }; &iris { From 1da12032d304da72d50fe42bea8ef4852e264c6c Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 27 Feb 2026 13:29:40 +0800 Subject: [PATCH 0237/1058] FROMLIST: arm64: dts: qcom: hamoa-iot-evk-camera-imx577: Add DT overlay Enable IMX577 via CCI on Hamoa EVK Core Kit. The Hamoa EVK board does not include a camera sensor by default, this DTSO has enabled the Arducam 12.3MP IMX577 Mini Camera Module on the CSI-1 interface. Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260227-hamoa_evk-v1-2-36f895a24d8f@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../dts/qcom/hamoa-iot-evk-camera-imx577.dtso | 81 +++++++++++++++++++ arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 16 ++++ 3 files changed, 100 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..2221868af77b7 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -17,9 +17,12 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb dtb-$(CONFIG_ARCH_QCOM) += eliza-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtbo +hamoa-iot-evk-camera-imx577-dtbs := hamoa-iot-evk.dtb hamoa-iot-evk-camera-imx577.dtbo hamoa-iot-evk-el2-dtbs := hamoa-iot-evk.dtb x1-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-lenovo-ideacentre-mini-01q8x10.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq5018-rdp432-c2.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso new file mode 100644 index 0000000000000..f45a7fbd14b1f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&{/} { + vreg_cam1_1p8: regulator-cam1 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1"; + startup-delay-us = <1000>; + enable-active-high; + gpio = <&tlmm 19 GPIO_ACTIVE_HIGH>; + }; +}; + +&camss { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + csiphy1_ep: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep>; + }; + }; + }; +}; + +&cci0 { + status = "okay"; +}; + +&cci0_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 110 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam1_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + dvdd-supply = <&vreg_cam1_1p8>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + imx577_ep: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; + +&csiphy1 { + vdda-0p8-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index c7ba4b353ddd2..f751309c7bf08 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -1341,6 +1341,22 @@ }; &tlmm { + cam1_default: cam1-default-state { + mclk-pins { + pins = "gpio97"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + rst-pins { + pins = "gpio110"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 796d26e55d584e66ca0110cd1aaf0fdd6852020b Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:35 +0530 Subject: [PATCH 0238/1058] FROMLIST: arm64: dts: qcom: x1e80100: Remove interconnect from SCM device Interconnect from SCM device are optional and were added to get additional performance benefit. These nodes however delays the SCM firmware device probe due to dependency on interconnect and results in NULL pointer dereference for the users of SCM device driver APIs, such as PDC driver. Remove them from the scm device to unblock the user. Link: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-1-760c8593ce50@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 04f96f88d6965..c0953dd459c2b 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -527,8 +527,7 @@ firmware { scm: scm { compatible = "qcom,scm-x1e80100", "qcom,scm"; - interconnects = <&aggre2_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + /* TODO: add interconnects */ qcom,dload-mode = <&tcsr 0x19000>; }; From ca66fb0a17a34126ebf0e223079416a8d827f344 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:38 +0530 Subject: [PATCH 0239/1058] FROMLIST: arm64: dts: qcom: x1e80100: Add deepest idle state Add deepest idle state along with pdc config reg to make GPIO IRQs work as wakeup capable interrupts in deepest idle state. Add QMP handle to allow PDC device to place a SoC level low power mode restriction. Link: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-4-760c8593ce50@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index c0953dd459c2b..64c337b7e9468 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -305,6 +305,14 @@ exit-latency-us = <4000>; min-residency-us = <7000>; }; + + domain_ss3: domain-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x0200c354>; + entry-latency-us = <2800>; + exit-latency-us = <4400>; + min-residency-us = <9000>; + }; }; }; @@ -666,7 +674,7 @@ system_pd: power-domain-system { #power-domain-cells = <0>; - /* TODO: system-wide idle states */ + domain-idle-states = <&domain_ss3>; }; reboot-mode { @@ -6698,8 +6706,10 @@ pdc: interrupt-controller@b220000 { compatible = "qcom,x1e80100-pdc", "qcom,pdc"; - reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>; - + reg = <0 0x0b220000 0 0x30000>, + <0 0x174000f0 0 0x64>, + <0 0x0b2045e8 0 0x4>; + qcom,qmp = <&aoss_qmp>; qcom,pdc-ranges = <0 480 42>, <42 251 5>, <47 522 52>, <99 609 32>, <131 717 12>, <143 816 19>; From d986f9585e05c20eed709ab557eb0f488f3be592 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 31 Dec 2025 15:48:46 +0530 Subject: [PATCH 0240/1058] FROMLIST: arm64: dts: qcom: purwa: Drop the Hamoa workaround for PDC Purwa shares the Hamoa (X1E80100) PDC device, but the hardware register bug addressed in commit e9a48ea4d90b ("irqchip/qcom-pdc: Workaround hardware register bug on X1E80100") is already fixed in Purwa silicon. Hamoa compatible forces the software workaround. Use the Purwa specific compatible string for the PDC node to remove the workaround from Purwa. Fixes: f08edb529916 ("arm64: dts: qcom: Add X1P42100 SoC and CRD") Link: https://lore.kernel.org/r/20251231-purwa_pdc-v1-2-2b4979dd88ad@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/purwa.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 81007578a7088..25c3baa4a9139 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -188,6 +188,10 @@ compatible = "qcom,x1p42100-qmp-gen4x4-pcie-phy"; }; +&pdc { + compatible = "qcom,x1p42100-pdc", "qcom,pdc"; +}; + &qfprom { gpu_speed_bin: gpu-speed-bin@119 { reg = <0x119 0x2>; From 10a2bb26a5dc22154cf88277aca1e6d4b36259fc Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 10 Apr 2026 02:38:51 +0530 Subject: [PATCH 0241/1058] FROMLIST: arm64: dts: qcom: purwa: Fix GPU IOMMU property Purwa's GPU does not support SID 1, which is typically used for LPAC-related traffic. Remove SID 1 from the GPU node's iommus property to accurately describe the hardware. This fixes the splat below, seen with some versions of Gunyah hypervisor: Internal error: synchronous external abort: 0000000096000010 [#1] SMP CPU: 0 UID: 0 PID: 80 Comm: kworker/u33:2 Tainted: G M Tainted: [M]=MACHINE_CHECK Hardware name: Qualcomm Technologies, Inc. Purwa IoT EVK (DT) Workqueue: events_unbound deferred_probe_work_func pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : arm_smmu_write_s2cr+0x9c/0xbc lr : arm_smmu_master_install_s2crs+0x78/0xa4 sp : ffff80008039b570 x29: ffff80008039b570 x28: 0000000000000000 x27: ffffaddd62f1ab78 x26: ffff00080a4ff280 x25: 0000000000000018 x24: ffff00080b896480 x23: ffff00080ba9b7a0 x22: ffff00080bb05160 x21: 0000000000000000 x20: 0000000000000000 x19: 0000000000000001 x18: 00000000ffffffff x17: 0000000000000000 x16: 0000000000000000 x15: ffff80008039b1d0 x14: ffff80010039b37d x13: 00746c7561662d74 x12: 0000000000000000 x11: ffff00080b7fbd98 x10: ffffffffffffffc0 x9 : ffffffffffffffff x8 : 0000000000000228 x7 : 0000000000000e87 x6 : 0000000000000000 x5 : 0000000000000000 x4 : ffff00080a4ff280 x3 : 0000000000000000 x2 : ffff800082a40c04 x1 : 0000000000000000 x0 : ffff800082a40000 Call trace: arm_smmu_write_s2cr+0x9c/0xbc (P) arm_smmu_master_install_s2crs+0x78/0xa4 arm_smmu_attach_dev+0xb0/0x1d8 __iommu_device_set_domain+0x84/0x11c __iommu_group_set_domain_internal+0x60/0x120 __iommu_attach_group+0x88/0x9c iommu_attach_device+0x6c/0xa0 msm_iommu_new.part.0+0x84/0xe4 [msm] msm_iommu_gpu_new+0x3c/0x104 [msm] adreno_iommu_create_vm+0x24/0xc8 [msm] a6xx_create_vm+0x48/0x78 [msm] msm_gpu_init+0x2d8/0x508 [msm] adreno_gpu_init+0x208/0x324 [msm] a6xx_gpu_init+0x604/0x8cc [msm] adreno_bind+0xb4/0x124 [msm] component_bind_all+0x114/0x23c msm_drm_init+0x1b0/0x1ec [msm] msm_drm_bind+0x30/0x3c [msm] try_to_bring_up_aggregate_device+0x164/0x1d0 __component_add+0xa4/0x16c component_add+0x14/0x20 msm_dp_display_probe_tail+0x4c/0xac [msm] msm_dp_auxbus_done_probe+0x14/0x20 [msm] dp_aux_ep_probe+0x4c/0xf4 [drm_dp_aux_bus] really_probe+0xbc/0x29c __driver_probe_device+0x78/0x12c driver_probe_device+0x3c/0x15c __device_attach_driver+0xb8/0x134 bus_for_each_drv+0x88/0xe8 __device_attach+0xa0/0x190 device_initial_probe+0x50/0x54 bus_probe_device+0x38/0xa4 deferred_probe_work_func+0x88/0xc0 process_one_work+0x148/0x28c worker_thread+0x2cc/0x3d4 kthread+0x12c/0x204 ret_from_fork+0x10/0x20 ---[ end trace 0000000000000000 ]--- Fixes: 1aa0b4e36436 ("arm64: dts: qcom: x1p42100: Add GPU support") Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20260410-purwa-gpu-dt-fix-v1-1-4637892156cf@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/purwa.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 25c3baa4a9139..11e54f47f9ac7 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -69,6 +69,8 @@ &gpu { compatible = "qcom,adreno-43030c00", "qcom,adreno"; + iommus = <&adreno_smmu 0 0x0>; + nvmem-cells = <&gpu_speed_bin>; nvmem-cell-names = "speed_bin"; From 7faf1ce6b6f56d1c6d01af499f7332d7f4296780 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:33 +0800 Subject: [PATCH 0242/1058] FROMLIST: arm64: dts: qcom: purwa: Add camss node Add node for the X1P42100 camera subsystem. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-3-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa.dtsi | 158 ++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 11e54f47f9ac7..936cd80a04cc4 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -19,6 +19,8 @@ /delete-node/ &cpu_pd9; /delete-node/ &cpu_pd10; /delete-node/ &cpu_pd11; +/delete-node/ &csiphy1; +/delete-node/ &csiphy2; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; /delete-node/ &pcie3_phy; @@ -50,6 +52,162 @@ /delete-node/ &cluster2_rep_2_3; /delete-node/ &apss_funnel_in2; +&camss { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x1860 0x60>, + <&apps_smmu 0x18e0 0x00>, + <&apps_smmu 0x19a0 0x20>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "top"; + + phys = <&csiphy0 PHY_TYPE_DPHY>, + <&csiphy4 PHY_TYPE_DPHY>; + phy-names = "csiphy0", + "csiphy4"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; + }; + }; + }; +}; + &camcc { compatible = "qcom,x1p42100-camcc"; }; From c6250158e94421c287462ff9ca4bb00db8b78387 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:34 +0800 Subject: [PATCH 0243/1058] FROMLIST: arm64: dts: qcom: purwa-iot-evk: Add camss node enable camss node for purwa iot evk board camss tpg support. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-4-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index ad503beec1d3d..eef03f1eb2a95 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -734,6 +734,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c3 { clock-frequency = <400000>; From 48bdd8500e0fd25a54f0383d929cb791404220e9 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 27 Apr 2026 15:34:55 +0530 Subject: [PATCH 0244/1058] FROMLIST: arm64: dts: qcom: x1-crd: Add Embedded controller node Add embedded controller node for Hamoa/Purwa CRDs which adds fan control, temperature sensors, access to EC internal state changes and suspend entry/exit notifications to the EC. Link: https://lore.kernel.org/lkml/20260427-add-driver-for-ec-v8-4-702f74e495f7@oss.qualcomm.com/ Signed-off-by: Sibi Sankar Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Co-developed-by: Anvesh Jain P Signed-off-by: Anvesh Jain P --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 3f62ec0241691..818475cee571f 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -1164,6 +1164,16 @@ #phy-cells = <0>; }; + + embedded-controller@76 { + compatible = "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; }; &i2c7 { @@ -1629,6 +1639,12 @@ }; }; + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 74f7cb5a23bb8c872a18c20fe21d3bd1ecfad7e3 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 27 Apr 2026 15:34:56 +0530 Subject: [PATCH 0245/1058] FROMLIST: arm64: dts: qcom: hamoa-iot-evk: Add Embedded controller node Add embedded controller node for Hamoa IOT EVK boards which adds fan control, temperature sensors, access to EC internal state changes and suspend entry/exit notifications to the EC. Link: https://lore.kernel.org/lkml/20260427-add-driver-for-ec-v8-5-702f74e495f7@oss.qualcomm.com/ Signed-off-by: Sibi Sankar Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Reviewed-by: Gaurav Kohli Tested-by: Gaurav Kohli Co-developed-by: Anvesh Jain P Signed-off-by: Anvesh Jain P --- arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index f751309c7bf08..c4c04cfdb557a 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -839,6 +839,16 @@ pinctrl-0 = <&eusb6_reset_n>; pinctrl-names = "default"; }; + + embedded-controller@76 { + compatible = "qcom,hamoa-iot-evk-ec", "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; }; &i2c7 { @@ -1357,6 +1367,12 @@ }; }; + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From cf3278c12416f1a8b4efc81d291ec29e4a6f4fa9 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 29 Apr 2026 15:43:55 +0800 Subject: [PATCH 0246/1058] FROMLIST: arm64: dts: qcom: purwa: Override Iris clocks and operating points The Iris block on X1P differs from SM8550/X1E in its clock configuration and requires a dedicated OPP table. The node inherited from the X1E cannot be reused directly, and the fallback compatible "qcom,sm8550-iris" cannot be applied. Override the inherited clocks, clock-names, and operating points, and replaces them with the X1P42100-specific definitions. A new OPP table is provided to support the correct performance levels on this platform. Link: https://lore.kernel.org/linux-arm-msm/20260429-enable_iris_on_purwa-v5-4-438fa96da248@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Dikshita Agarwal Reviewed-by: Dmitry Baryshkov Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/purwa.dtsi | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 936cd80a04cc4..2b6106c15aee2 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -23,6 +23,7 @@ /delete-node/ &csiphy2; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; +/delete-node/ &iris_opp_table; /delete-node/ &pcie3_phy; /delete-node/ &thermal_aoss3; /delete-node/ &thermal_cpu2_0_btm; @@ -339,6 +340,55 @@ compatible = "qcom,x1p42100-gpucc"; }; +&iris { + compatible = "qcom,x1p42100-iris"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&videocc VIDEO_CC_MVS0_BSE_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "vcodec0_bse"; + + operating-points-v2 = <&iris_opp_table_x1p42100>; + + iris_opp_table_x1p42100: opp-table { + compatible = "operating-points-v2"; + + opp-210000000 { + opp-hz = /bits/ 64 <210000000 105000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000 150000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_svs>; + }; + + opp-335000000 { + opp-hz = /bits/ 64 <335000000 167500000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-424000000 { + opp-hz = /bits/ 64 <424000000 212000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_nom>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000 250000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_turbo>; + }; + }; +}; + /* PCIe3 has half the lanes compared to X1E80100 */ &pcie3 { num-lanes = <4>; From 729f6cde2b98097739ba1a563ca9e2a1b6d51544 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 29 Apr 2026 15:43:56 +0800 Subject: [PATCH 0247/1058] FROMLIST: arm64: dts: qcom: purwa-iot-som: enable video Enable video nodes on the purwa-iot-som board. Link: https://lore.kernel.org/linux-arm-msm/20260429-enable_iris_on_purwa-v5-5-438fa96da248@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dikshita Agarwal Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi index 394e65518ac50..ff8621f875058 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi @@ -389,6 +389,10 @@ firmware-name = "qcom/x1p42100/gen71500_zap.mbn"; }; +&iris { + status = "okay"; +}; + &pcie3 { pinctrl-0 = <&pcie3_default>; pinctrl-names = "default"; From d82f489168ed6f93aa7b2ec741753455188c5815 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 7 Apr 2026 11:07:38 +0530 Subject: [PATCH 0248/1058] PENDING: arm64: dts: qcom: hamoa: switch iris iommus to iommu-map Switch the iris video codec node in hamoa from the legacy 'iommus' property to 'iommu-map', using IRIS_NON_PIXEL_VCODEC and IRIS_PIXEL function IDs to identify the non-pixel and pixel context bank SMMU stream mappings respectively. Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 64c337b7e9468..768ce38a6002d 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -5703,8 +5704,8 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; + iommu-map = , + ; dma-coherent; /* From e421ae627cfcbda70ed48b0b80a7504477b673e4 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 7 May 2026 11:52:37 +0530 Subject: [PATCH 0249/1058] FROMLIST: arm64: dts: qcom: hamoa: Enable LLCC/DDR/DDR_QOS dvfs On Qualcomm Hamoa SoCs, the memlat governor and the mechanism to control the LLCC and DDR/DDR_QOS is hosted on the CPU Control Processor (CPUCP). Add the vendor protocol node to the existing SCMI transport to enable QCOM SCMI Generic Extension protocol on Hamoa SoCs. Link: https://lore.kernel.org/lkml/20260507062237.78051-9-sibi.sankar@oss.qualcomm.com/ Signed-off-by: Sibi Sankar --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 768ce38a6002d..2904941ea0827 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -553,6 +553,10 @@ reg = <0x13>; #power-domain-cells = <1>; }; + + scmi_vendor: protocol@80 { + reg = <0x80>; + }; }; }; From 25fcc9c1b18eb5310e2d83f3f79a7eaeebe62c58 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Thu, 16 Apr 2026 17:04:48 +0530 Subject: [PATCH 0250/1058] FROMLIST: arm64: dts: qcom: purwa-iot-evk: Update TSENS thermal zone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purwa IOT boards support a different thermal junction temperature specification compared to the base Purwa platform due to package level differences. Update the passive trip thresholds to 105°C to align with the higher temperature specification. Signed-off-by: Gaurav Kohli Link: https://lore.kernel.org/r/20260416-purwa_high_tj-v1-1-b538f98d42da@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index eef03f1eb2a95..bff2f5cd9d70d 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -1329,6 +1329,38 @@ }; }; +&thermal_gpuss_0 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_1 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_2 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_3 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + &tlmm { edp_reg_en: edp-reg-en-state { pins = "gpio70"; From e39fb5d14bd7a9b4499a0866e5615e7a1c9123de Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 4 Jun 2026 13:50:54 +0530 Subject: [PATCH 0251/1058] PENDING: arm64: dts: enable iris driver for hamoa kvm Add video firmware node to enable video kvm on the hamoa. Signed-off-by: Renjiang Han --- arch/arm64/boot/dts/qcom/x1-el2.dtso | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1-el2.dtso b/arch/arm64/boot/dts/qcom/x1-el2.dtso index ee006742d6f3b..8bbe5e61402b0 100644 --- a/arch/arm64/boot/dts/qcom/x1-el2.dtso +++ b/arch/arm64/boot/dts/qcom/x1-el2.dtso @@ -17,8 +17,10 @@ }; &iris { - /* TODO: Add video-firmware iommus to start IRIS from EL2 */ - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x1942 0x0>; + }; }; /* From 1bba27c2c7bc4eaa5c57ad85a89cd2d2bea86953 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 19:36:05 +0800 Subject: [PATCH 0252/1058] FROMLIST: arm64: dts: qcom: hamoa: Add label properties to CoreSight devices Add label properties to TPDM and CTI nodes in the hamoa device tree to provide human-readable identifiers for each CoreSight device. These labels allow userspace tools and the CoreSight framework to identify devices by name rather than by base address. Link: https://lore.kernel.org/linux-arm-msm/20260414-add-label-to-coresight-device-v2-7-5017d07358f2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 2904941ea0827..21588e0bd2cbd 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -7596,6 +7596,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -7653,6 +7654,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -7915,6 +7917,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rpdm_mxa"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7934,6 +7937,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_gcc"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7953,6 +7957,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -7972,6 +7977,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_lpass"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8015,6 +8021,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp_cscti"; }; tpdm@109d0000 { @@ -8023,6 +8030,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_qm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8043,6 +8051,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8063,6 +8072,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8310,6 +8320,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8329,6 +8340,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8348,6 +8360,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8367,6 +8380,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8386,6 +8400,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8405,6 +8420,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_lpi"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8475,6 +8491,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlmm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8523,6 +8540,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlct"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -8542,6 +8560,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ipcc"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8675,6 +8694,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rdpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8694,6 +8714,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rdpm_mx"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8790,6 +8811,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_tmess_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -8894,6 +8916,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_0"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -8913,6 +8936,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_1"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -8932,6 +8956,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_2"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -8951,6 +8976,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_3"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -8970,6 +8996,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_4"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -8989,6 +9016,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_5"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -9008,6 +9036,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_6"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -9027,6 +9056,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llcc_7"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; From 7b74eb792eb2a8e040839dd1555a865a6b8e1a97 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 9 Feb 2026 14:24:25 +0000 Subject: [PATCH 0253/1058] dt-bindings: mfd: qcom,spmi-pmic: add compatibles for pm4124-codec Qualcomm Agatti SoC has PM4125 PMIC, which includes audio codec. Audio codec has TX and RX soundwire slave devices to connect to on-chip soundwire master. Add missing qcom,pm4125-codec compatible to pattern of audio-codec node properties in mfd qcom,spmi-pmic schema to complete the audio codec support. Signed-off-by: Alexey Klimov [Srini: reworked the patch] Signed-off-by: Srinivas Kandagatla Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260209142428.214428-2-srinivas.kandagatla@oss.qualcomm.com --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 644c42b5e2e57..bdd304e9eac13 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -146,7 +146,11 @@ patternProperties: "^audio-codec@[0-9a-f]+$": type: object - $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# + oneOf: + - $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# + - properties: + compatible: + const: qcom,pm4125-codec "^battery@[0-9a-f]+$": type: object From c183cd4cb7920adf286e685d192373d7e4c92b64 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 9 Feb 2026 14:24:26 +0000 Subject: [PATCH 0254/1058] arm64: dts: qcom: agatti: add LPASS devices The rxmacro, txmacro, vamacro, soundwire nodes, lpass clock controllers are required to support audio playback and audio capture on sm6115 and its derivatives. Signed-off-by: Alexey Klimov Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-3-srinivas.kandagatla@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/agatti.dtsi | 189 +++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index f0b6ae9b81528..6df8977496333 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -770,6 +770,42 @@ drive-strength = <8>; }; }; + + lpass_tx_swr_active: lpass-tx-swr-active-state { + clk-pins { + pins = "gpio0"; + function = "swr_tx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio1", "gpio2"; + function = "swr_tx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; + + lpass_rx_swr_active: lpass-rx-swr-active-state { + clk-pins { + pins = "gpio3"; + function = "swr_rx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio4", "gpio5"; + function = "swr_rx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; }; gcc: clock-controller@1400000 { @@ -2239,6 +2275,159 @@ }; }; + rxmacro: codec@a600000 { + compatible = "qcom,sm6115-lpass-rx-macro"; + reg = <0x0 0xa600000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <22579200>, + <22579200>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@a610000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a610000 0x0 0x2000>; + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + + resets = <&lpass_audiocc 0>; + reset-names = "swr_audio_cgcr"; + + label = "RX"; + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + + txmacro: codec@a620000 { + compatible = "qcom,sm6115-lpass-tx-macro"; + reg = <0x0 0x0a620000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + lpass_audiocc: clock-controller@a6a9000 { + compatible = "qcom,sm6115-lpassaudiocc"; + reg = <0x0 0x0a6a9000 0x0 0x1000>; + #reset-cells = <1>; + }; + + vamacro: codec@a730000 { + compatible = "qcom,sm6115-lpass-va-macro"; + reg = <0x0 0x0a730000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", + "dcodec", + "npl"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + }; + + swr0: soundwire@a740000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a740000 0x0 0x2000>; + interrupts = , + ; + clocks = <&txmacro>; + clock-names = "iface"; + + resets = <&lpasscc 0>; + reset-names = "swr_audio_cgcr"; + + label = "VA_TX"; + qcom,din-ports = <3>; + qcom,dout-ports = <0>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + lpasscc: clock-controller@a7ec000 { + compatible = "qcom,sm6115-lpasscc"; + reg = <0x0 0x0a7ec000 0x0 0x1000>; + #reset-cells = <1>; + }; + remoteproc_adsp: remoteproc@ab00000 { compatible = "qcom,qcm2290-adsp-pas", "qcom,sm6115-adsp-pas"; reg = <0x0 0x0ab00000 0x0 0x100>; From b22813b4a12019a09088440b032ef4042825327e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 9 Feb 2026 14:24:27 +0000 Subject: [PATCH 0255/1058] arm64: dts: arduino-imola: add support for sound Add support for sound on Arduino UNO Q board, which includes - Headset playback and record. - Lineout Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-4-srinivas.kandagatla@oss.qualcomm.com --- .../boot/dts/qcom/qrb2210-arduino-imola.dts | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index bf088fa9807f0..5266f89feaaf2 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -110,6 +110,98 @@ leds = <&ledr>, <&ledg>, <&ledb>; }; + sound { + compatible = "qcom,qrb2210-sndcard"; + model = "Arduino-Imola-HPH-LOUT"; + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2"; + + mm1-dai-link { + link-name = "MultiMedia1"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + mm2-dai-link { + link-name = "MultiMedia2"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>; + }; + }; + + mm3-dai-link { + link-name = "MultiMedia3"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; + }; + }; + + hph-playback-dai-link { + link-name = "HPH Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + lo-playback-dai-link { + link-name = "LO Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + ear-playback-dai-link { + link-name = "Ear Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + hph-capture-dai-link { + link-name = "HP Capture"; + cpu { + sound-dai = <&q6afedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 1>, <&swr0 0>, <&txmacro 0>; + }; + }; + }; + vreg_anx_30: regulator-anx-30 { compatible = "regulator-fixed"; regulator-name = "anx30"; @@ -421,6 +513,51 @@ }; }; +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000{ + compatible = "qcom,pm4125-codec"; + reg =<0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s4>; + vdd-pa-vpos-supply = <&pm4125_s4>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + }; + }; +}; + +&swr0 { + pinctrl-0 = <&lpass_tx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + }; +}; + +&swr1 { + pinctrl-0 = <&lpass_rx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + &tlmm { jmisc_gpio18: jmisc-gpio18-state { pins = "gpio18"; From a2d85fe547167dbd8fc59618907c20a6f17d2e5a Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 9 Feb 2026 14:24:28 +0000 Subject: [PATCH 0256/1058] arm64: defconfig: Enable Agatti audio drivers Enable reset controller and pm4125 audio codec driver that are required to enable audio support on Qualcomm Agatti SoC based platforms. Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-5-srinivas.kandagatla@oss.qualcomm.com --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc5..68c4ddbecb5e3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1152,6 +1152,8 @@ CONFIG_SND_SOC_GTM601=m CONFIG_SND_SOC_MAX98090=m CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m +CONFIG_SND_SOC_PM4125_SDW=m +CONFIG_SND_SOC_PCM3168A_I2C=m CONFIG_SND_SOC_RK3308=m CONFIG_SND_SOC_RK817=m CONFIG_SND_SOC_RT5640=m @@ -1568,6 +1570,7 @@ CONFIG_SM_GPUCC_8450=m CONFIG_SM_GPUCC_8550=m CONFIG_SM_GPUCC_8650=m CONFIG_SM_GPUCC_8750=m +CONFIG_SM_LPASSCC_6115=m CONFIG_SM_TCSRCC_8550=y CONFIG_SM_TCSRCC_8650=y CONFIG_SM_TCSRCC_8750=m From 723e3ef44a909d5e2a4b270d6bccdbeec975b9d1 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 1 Jul 2026 14:14:36 +0800 Subject: [PATCH 0257/1058] FROMLIST: arm64: dts: qcom: hamoa: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in hamoa. Set up CDSP cooling for both instances by throttling the cdsp, when it reaches 95°C. Link: https://lore.kernel.org/linux-devicetree/20260609-qmi-tmd-v3-8-291a2ff4c634@oss.qualcomm.com/ Signed-off-by: Dipa Ramesh Mantre Signed-off-by: Xin Liu --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 21588e0bd2cbd..99631cde48e83 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -10463,6 +10463,9 @@ status = "disabled"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + glink-edge { interrupts-extended = <&ipcc IPCC_CLIENT_CDSP IPCC_MPROC_SIGNAL_GLINK_QMP @@ -11050,6 +11053,7 @@ }; thermal_nsp0: nsp0-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 1>; trips { @@ -11059,15 +11063,30 @@ type = "hot"; }; + nsp0_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp0-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp1: nsp1-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 2>; trips { @@ -11077,15 +11096,30 @@ type = "hot"; }; + nsp1_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp1-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp2: nsp2-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 3>; trips { @@ -11095,15 +11129,30 @@ type = "hot"; }; + nsp2_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp2-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp3: nsp3-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 4>; trips { @@ -11113,12 +11162,26 @@ type = "hot"; }; + nsp3_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp3-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_gpuss_0: gpuss-0-thermal { From fb45c95e03ac5869e35d5087fd47a1a76f0c759a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:03 +0200 Subject: [PATCH 0258/1058] dmaengine: constify struct dma_descriptor_metadata_ops There's no reason for the instances of this struct to be modifiable. Constify the pointer in struct dma_async_tx_descriptor and all drivers currently using it. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Reviewed-by: Radhey Shyam Pandey Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-1-56f67da84c05@oss.qualcomm.com --- drivers/dma/ti/k3-udma.c | 2 +- drivers/dma/xilinx/xilinx_dma.c | 2 +- include/linux/dmaengine.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 1cf158eb7bdb5..fb21e0df5ab7b 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -3408,7 +3408,7 @@ static int udma_set_metadata_len(struct dma_async_tx_descriptor *desc, return 0; } -static struct dma_descriptor_metadata_ops metadata_ops = { +static const struct dma_descriptor_metadata_ops metadata_ops = { .attach = udma_attach_metadata, .get_ptr = udma_get_metadata_ptr, .set_len = udma_set_metadata_len, diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 404235c173538..165b11a7c776a 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -653,7 +653,7 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx, return seg->hw.app; } -static struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = { +static const struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = { .get_ptr = xilinx_dma_get_metadata_ptr, }; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b3d251c9734e9..5244edb90e7e7 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -623,7 +623,7 @@ struct dma_async_tx_descriptor { void *callback_param; struct dmaengine_unmap_data *unmap; enum dma_desc_metadata_mode desc_metadata_mode; - struct dma_descriptor_metadata_ops *metadata_ops; + const struct dma_descriptor_metadata_ops *metadata_ops; #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH struct dma_async_tx_descriptor *next; struct dma_async_tx_descriptor *parent; From 1ec1341622992e6ec93052e4bc85cc572bdaf431 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:04 +0200 Subject: [PATCH 0259/1058] dmaengine: qcom: bam_dma: free interrupt before the clock in error path The BAM interrupt is requested with a devres helper and so on error it's freed after probe() returns. We disable the clock before freeing or masking it so it may still fire and we may end up reading BAM registers with clock disabled. Stop using devres for interrupts as we free it in remove() manually anyway. Add an appropriate label and free the interrupt before disabling the clock in error path and in remove(). Fixes: e7c0fe2a5c84 ("dmaengine: add Qualcomm BAM dma driver") Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=2 Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-2-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 1bb26af0405f3..fc155e0d1870c 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1332,8 +1332,7 @@ static int bam_dma_probe(struct platform_device *pdev) for (i = 0; i < bdev->num_channels; i++) bam_channel_init(bdev, &bdev->channels[i], i); - ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq, - IRQF_TRIGGER_HIGH, "bam_dma", bdev); + ret = request_irq(bdev->irq, bam_dma_irq, IRQF_TRIGGER_HIGH, "bam_dma", bdev); if (ret) goto err_bam_channel_exit; @@ -1366,7 +1365,7 @@ static int bam_dma_probe(struct platform_device *pdev) ret = dma_async_device_register(&bdev->common); if (ret) { dev_err(bdev->dev, "failed to register dma async device\n"); - goto err_bam_channel_exit; + goto err_free_irq; } ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate, @@ -1385,6 +1384,8 @@ static int bam_dma_probe(struct platform_device *pdev) err_unregister_dma: dma_async_device_unregister(&bdev->common); +err_free_irq: + free_irq(bdev->irq, bdev); err_bam_channel_exit: for (i = 0; i < bdev->num_channels; i++) tasklet_kill(&bdev->channels[i].vc.task); @@ -1401,6 +1402,8 @@ static void bam_dma_remove(struct platform_device *pdev) struct bam_device *bdev = platform_get_drvdata(pdev); u32 i; + free_irq(bdev->irq, bdev); + pm_runtime_force_suspend(&pdev->dev); of_dma_controller_free(pdev->dev.of_node); @@ -1409,8 +1412,6 @@ static void bam_dma_remove(struct platform_device *pdev) /* mask all interrupts for this execution environment */ writel_relaxed(0, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); - devm_free_irq(bdev->dev, bdev->irq, bdev); - for (i = 0; i < bdev->num_channels; i++) { bam_dma_terminate_all(&bdev->channels[i].vc.chan); tasklet_kill(&bdev->channels[i].vc.task); From 4e810ace0c513d50c688c786681d1e28db07d74c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:05 +0200 Subject: [PATCH 0260/1058] dmaengine: qcom: bam_dma: convert tasklet to a BH workqueue BH workqueues are a modern mechanism, aiming to replace legacy tasklets. Let's convert the BAM DMA driver to using the high-priority variant of the BH workqueue. [Vinod: suggested using the BG workqueue instead of the regular one running in process context] Suggested-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Reviewed-by: Bjorn Andersson Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-3-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index fc155e0d1870c..ea3df28e777f9 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "../virt-dma.h" @@ -426,8 +427,8 @@ struct bam_device { struct clk *bamclk; int irq; - /* dma start transaction tasklet */ - struct tasklet_struct task; + /* dma start transaction workqueue */ + struct work_struct work; }; /** @@ -892,7 +893,7 @@ static u32 process_channel_irqs(struct bam_device *bdev) /* * if complete, process cookie. Otherwise * push back to front of desc_issued so that - * it gets restarted by the tasklet + * it gets restarted by the work queue. */ if (!async_desc->num_desc) { vchan_cookie_complete(&async_desc->vd); @@ -922,9 +923,9 @@ static irqreturn_t bam_dma_irq(int irq, void *data) srcs |= process_channel_irqs(bdev); - /* kick off tasklet to start next dma transfer */ + /* kick off the work queue to start next dma transfer */ if (srcs & P_IRQ) - tasklet_schedule(&bdev->task); + queue_work(system_bh_highpri_wq, &bdev->work); ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) @@ -1120,14 +1121,14 @@ static void bam_start_dma(struct bam_chan *bchan) } /** - * dma_tasklet - DMA IRQ tasklet - * @t: tasklet argument (bam controller structure) + * bam_dma_work() - DMA interrupt work queue callback + * @work: work queue struct embedded in the BAM controller device struct * * Sets up next DMA operation and then processes all completed transactions */ -static void dma_tasklet(struct tasklet_struct *t) +static void bam_dma_work(struct work_struct *work) { - struct bam_device *bdev = from_tasklet(bdev, t, task); + struct bam_device *bdev = from_work(bdev, work, work); struct bam_chan *bchan; unsigned int i; @@ -1140,14 +1141,13 @@ static void dma_tasklet(struct tasklet_struct *t) if (!list_empty(&bchan->vc.desc_issued) && !IS_BUSY(bchan)) bam_start_dma(bchan); } - } /** * bam_issue_pending - starts pending transactions * @chan: dma channel * - * Calls tasklet directly which in turn starts any pending transactions + * Calls work queue directly which in turn starts any pending transactions */ static void bam_issue_pending(struct dma_chan *chan) { @@ -1316,14 +1316,14 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_disable_clk; - tasklet_setup(&bdev->task, dma_tasklet); + INIT_WORK(&bdev->work, bam_dma_work); bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels, sizeof(*bdev->channels), GFP_KERNEL); if (!bdev->channels) { ret = -ENOMEM; - goto err_tasklet_kill; + goto err_workqueue_cancel; } /* allocate and initialize channels */ @@ -1389,8 +1389,8 @@ static int bam_dma_probe(struct platform_device *pdev) err_bam_channel_exit: for (i = 0; i < bdev->num_channels; i++) tasklet_kill(&bdev->channels[i].vc.task); -err_tasklet_kill: - tasklet_kill(&bdev->task); +err_workqueue_cancel: + cancel_work_sync(&bdev->work); err_disable_clk: clk_disable_unprepare(bdev->bamclk); @@ -1424,7 +1424,7 @@ static void bam_dma_remove(struct platform_device *pdev) bdev->channels[i].fifo_phys); } - tasklet_kill(&bdev->task); + cancel_work_sync(&bdev->work); clk_disable_unprepare(bdev->bamclk); } From f927cc3cb77fe9b985faa704c78b79cc21a931a5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:06 +0200 Subject: [PATCH 0261/1058] dmaengine: qcom: bam_dma: Extend the driver's device match data In preparation for supporting the pipe locking feature flag, extend the amount of information we can carry in device match data: create a separate structure and make the register information one of its fields. This way, in subsequent patches, it will be just a matter of adding a new field to the device data. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-4-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index ea3df28e777f9..8ce0fe085c5fe 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -113,6 +113,10 @@ struct reg_offset_data { unsigned int pipe_mult, evnt_mult, ee_mult; }; +struct bam_device_data { + const struct reg_offset_data *reg_info; +}; + static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_CTRL] = { 0x0F80, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0F84, 0x00, 0x00, 0x00 }, @@ -142,6 +146,10 @@ static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1020, 0x00, 0x40, 0x00 }, }; +static const struct bam_device_data bam_v1_3_data = { + .reg_info = bam_v1_3_reg_info, +}; + static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0004, 0x00, 0x00, 0x00 }, @@ -171,6 +179,10 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_4_data = { + .reg_info = bam_v1_4_reg_info, +}; + static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_CTRL] = { 0x00000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x01000, 0x00, 0x00, 0x00 }, @@ -200,6 +212,10 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x13820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_7_data = { + .reg_info = bam_v1_7_reg_info, +}; + static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x1000, 0x00, 0x00, 0x00 }, @@ -229,6 +245,10 @@ static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0xC820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v2_0_data = { + .reg_info = bam_v2_0_reg_info, +}; + /* BAM CTRL */ #define BAM_SW_RST BIT(0) #define BAM_EN BIT(1) @@ -422,7 +442,7 @@ struct bam_device { bool powered_remotely; u32 active_channels; - const struct reg_offset_data *layout; + const struct bam_device_data *dev_data; struct clk *bamclk; int irq; @@ -440,7 +460,7 @@ struct bam_device { static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, enum bam_reg reg) { - const struct reg_offset_data r = bdev->layout[reg]; + const struct reg_offset_data r = bdev->dev_data->reg_info[reg]; return bdev->regs + r.base_offset + r.pipe_mult * pipe + @@ -1234,10 +1254,10 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan, } static const struct of_device_id bam_of_match[] = { - { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info }, - { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info }, - { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_reg_info }, - { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_reg_info }, + { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_data }, + { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_data }, + { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_data }, + { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_data }, {} }; @@ -1261,7 +1281,7 @@ static int bam_dma_probe(struct platform_device *pdev) return -ENODEV; } - bdev->layout = match->data; + bdev->dev_data = match->data; bdev->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bdev->regs)) From 76556265923bf1f56ccb582f2ed72f4ad95baeba Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:07 +0200 Subject: [PATCH 0262/1058] dmaengine: qcom: bam_dma: Add pipe_lock_supported flag support Extend the device match data with a flag indicating whether the IP supports the BAM lock/unlock feature. Set it to true on BAM IP versions 1.4.0 and above. Signed-off-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Acked-by: Manivannan Sadhasivam Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-5-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 8ce0fe085c5fe..f3e713a5259c2 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -115,6 +115,7 @@ struct reg_offset_data { struct bam_device_data { const struct reg_offset_data *reg_info; + bool pipe_lock_supported; }; static const struct reg_offset_data bam_v1_3_reg_info[] = { @@ -181,6 +182,7 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { static const struct bam_device_data bam_v1_4_data = { .reg_info = bam_v1_4_reg_info, + .pipe_lock_supported = true, }; static const struct reg_offset_data bam_v1_7_reg_info[] = { @@ -214,6 +216,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { static const struct bam_device_data bam_v1_7_data = { .reg_info = bam_v1_7_reg_info, + .pipe_lock_supported = true, }; static const struct reg_offset_data bam_v2_0_reg_info[] = { @@ -247,6 +250,7 @@ static const struct reg_offset_data bam_v2_0_reg_info[] = { static const struct bam_device_data bam_v2_0_data = { .reg_info = bam_v2_0_reg_info, + .pipe_lock_supported = true, }; /* BAM CTRL */ From 909e90d5f04f5cf76c0e70f0bb67d2a52433c5e9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:08 +0200 Subject: [PATCH 0263/1058] dmaengine: qcom: bam_dma: add support for BAM locking Add support for BAM pipe locking. To that end: when starting DMA on an RX channel - prepend the existing queue of issued descriptors with an additional "dummy" command descriptor with the LOCK bit set. Once the transaction is done (no more issued descriptors), issue one more dummy descriptor with the UNLOCK bit. We *must* wait until the transaction is signalled as done because we must not perform any writes into config registers while the engine is busy. The dummy writes must be issued into a scratchpad register of the client so provide a mechanism to communicate the right address via descriptor metadata. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-6-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 189 +++++++++++++++++++++++++++++-- include/linux/dma/qcom_bam_dma.h | 14 +++ 2 files changed, 196 insertions(+), 7 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index f3e713a5259c2..f4f258994264a 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -60,6 +62,8 @@ struct bam_desc_hw { #define DESC_FLAG_EOB BIT(13) #define DESC_FLAG_NWD BIT(12) #define DESC_FLAG_CMD BIT(11) +#define DESC_FLAG_LOCK BIT(10) +#define DESC_FLAG_UNLOCK BIT(9) struct bam_async_desc { struct virt_dma_desc vd; @@ -72,6 +76,10 @@ struct bam_async_desc { struct bam_desc_hw *curr_desc; + /* BAM locking infrastructure */ + struct scatterlist lock_sg; + struct bam_cmd_element lock_ce; + /* list node for the desc in the bam_chan list of descriptors */ struct list_head desc_node; enum dma_transfer_direction dir; @@ -425,6 +433,11 @@ struct bam_chan { struct list_head desc_list; struct list_head node; + + /* BAM locking infrastructure */ + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; + bool bam_locked; }; static inline struct bam_chan *to_bam_chan(struct dma_chan *common) @@ -638,8 +651,10 @@ static void bam_free_chan(struct dma_chan *chan) goto err; } - scoped_guard(spinlock_irqsave, &bchan->vc.lock) + scoped_guard(spinlock_irqsave, &bchan->vc.lock) { bam_reset_channel(bchan); + bchan->bam_locked = false; + } dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt, bchan->fifo_phys); @@ -686,6 +701,35 @@ static int bam_slave_config(struct dma_chan *chan, return 0; } +static int bam_metadata_attach(struct dma_async_tx_descriptor *desc, void *data, size_t len) +{ + struct bam_chan *bchan = to_bam_chan(desc->chan); + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_desc_metadata *metadata = data; + + if (!data) + return -EINVAL; + + if (!bdata->pipe_lock_supported) + /* + * The client wants to use locking but this BAM version doesn't + * support it. Don't return an error here as this will stop the + * client from using DMA at all for no reason. + */ + return 0; + + guard(spinlock_irqsave)(&bchan->vc.lock); + + bchan->scratchpad_addr = metadata->scratchpad_addr; + bchan->direction = metadata->direction; + + return 0; +} + +static const struct dma_descriptor_metadata_ops bam_metadata_ops = { + .attach = bam_metadata_attach, +}; + /** * bam_prep_slave_sg - Prep slave sg transaction * @@ -702,6 +746,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, void *context) { struct bam_chan *bchan = to_bam_chan(chan); + struct dma_async_tx_descriptor *tx_desc; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc; struct scatterlist *sg; @@ -757,7 +802,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, } while (remainder > 0); } - return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc = vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc->metadata_ops = &bam_metadata_ops; + + return tx_desc; } /** @@ -802,6 +850,7 @@ static int bam_dma_terminate_all(struct dma_chan *chan) } vchan_get_all_descriptors(&bchan->vc, &head); + bchan->bam_locked = false; } vchan_dma_desc_free_list(&bchan->vc, &head); @@ -859,6 +908,15 @@ static int bam_resume(struct dma_chan *chan) return 0; } +static void bam_dma_free_lock_desc(struct virt_dma_desc *vd) +{ + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct dma_chan *chan = vd->tx.chan; + + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + kfree(async_desc); +} + /** * process_channel_irqs - processes the channel interrupts * @bdev: bam controller @@ -919,13 +977,23 @@ static u32 process_channel_irqs(struct bam_device *bdev) * push back to front of desc_issued so that * it gets restarted by the work queue. */ + + list_del(&async_desc->desc_node); if (!async_desc->num_desc) { - vchan_cookie_complete(&async_desc->vd); + struct bam_desc_hw *hdesc = async_desc->desc; + u16 flags = le16_to_cpu(hdesc->flags); + + if (flags & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) { + if (flags & DESC_FLAG_UNLOCK) + bchan->bam_locked = false; + bam_dma_free_lock_desc(&async_desc->vd); + } else { + vchan_cookie_complete(&async_desc->vd); + } } else { list_add(&async_desc->vd.node, &bchan->vc.desc_issued); } - list_del(&async_desc->desc_node); } } @@ -1046,13 +1114,101 @@ static void bam_apply_new_config(struct bam_chan *bchan, bchan->reconfigure = 0; } +static struct bam_async_desc * +bam_make_lock_desc(struct bam_chan *bchan, unsigned long flag) +{ + struct dma_chan *chan = &bchan->vc.chan; + struct bam_async_desc *async_desc; + struct bam_desc_hw *desc; + struct virt_dma_desc *vd; + struct virt_dma_chan *vc; + unsigned int mapped; + + async_desc = kzalloc_flex(*async_desc, desc, 1, GFP_NOWAIT); + if (!async_desc) { + dev_err(bchan->bdev->dev, "failed to allocate the BAM lock descriptor\n"); + return ERR_PTR(-ENOMEM); + } + + sg_init_table(&async_desc->lock_sg, 1); + + async_desc->num_desc = 1; + async_desc->curr_desc = async_desc->desc; + async_desc->dir = DMA_MEM_TO_DEV; + + desc = async_desc->desc; + + bam_prep_ce_le32(&async_desc->lock_ce, bchan->scratchpad_addr, BAM_WRITE_COMMAND, 0); + sg_set_buf(&async_desc->lock_sg, &async_desc->lock_ce, sizeof(async_desc->lock_ce)); + + mapped = dma_map_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + if (!mapped) { + kfree(async_desc); + return ERR_PTR(-ENOMEM); + } + + desc->flags |= cpu_to_le16(DESC_FLAG_CMD | flag); + desc->addr = sg_dma_address(&async_desc->lock_sg); + desc->size = cpu_to_le16(sizeof(struct bam_cmd_element)); + + vc = &bchan->vc; + vd = &async_desc->vd; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = DMA_PREP_CMD; + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + return async_desc; +} + +static int bam_setup_pipe_lock(struct bam_chan *bchan) +{ + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_async_desc *lock_desc, *unlock_desc; + + lockdep_assert_held(&bchan->vc.lock); + + if (!bdata->pipe_lock_supported || !bchan->scratchpad_addr || + bchan->direction != DMA_MEM_TO_DEV) + return 0; + + /* + * Allocate both the LOCK and the UNLOCK descriptors up-front so the + * operation is all-or-nothing: if either allocation fails we free both + * and run the sequence unlocked rather than leave the pipe locked with + * no matching UNLOCK. + * + * Both are queued in-band around the currently issued work: the LOCK is + * prepended so it enters the FIFO first, the UNLOCK is appended so it is + * the last descriptor of the sequence. They are loaded together with the + * payload in a single operation so the engine executes LOCK, the work + * and UNLOCK as one ordered batch. + */ + lock_desc = bam_make_lock_desc(bchan, DESC_FLAG_LOCK); + if (IS_ERR(lock_desc)) + return PTR_ERR(lock_desc); + + unlock_desc = bam_make_lock_desc(bchan, DESC_FLAG_UNLOCK); + if (IS_ERR(unlock_desc)) { + bam_dma_free_lock_desc(&lock_desc->vd); + return PTR_ERR(unlock_desc); + } + + list_add(&lock_desc->vd.node, &bchan->vc.desc_issued); + list_add_tail(&unlock_desc->vd.node, &bchan->vc.desc_issued); + bchan->bam_locked = true; + + return 0; +} + /** * bam_start_dma - start next transaction * @bchan: bam dma channel */ static void bam_start_dma(struct bam_chan *bchan) { - struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc); + struct virt_dma_desc *vd; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc = NULL; struct bam_desc_hw *desc; @@ -1064,9 +1220,23 @@ static void bam_start_dma(struct bam_chan *bchan) lockdep_assert_held(&bchan->vc.lock); + vd = vchan_next_desc(&bchan->vc); if (!vd) return; + /* + * Wrap the issued work with a LOCK/UNLOCK pair exactly once, at the + * start of a fresh sequence and only when there is real work to lock + * around. On a re-entry after a full FIFO, we see the BAM is locked + * and must not add another pair we simply continue loading the + * remainder of the same locked sequence. + */ + if (!bchan->bam_locked) { + ret = bam_setup_pipe_lock(bchan); + if (ret == 0 && bchan->bam_locked) + vd = vchan_next_desc(&bchan->vc); + } + ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) return; @@ -1191,8 +1361,12 @@ static void bam_issue_pending(struct dma_chan *chan) */ static void bam_dma_free_desc(struct virt_dma_desc *vd) { - struct bam_async_desc *async_desc = container_of(vd, - struct bam_async_desc, vd); + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct bam_desc_hw *desc = async_desc->desc; + struct dma_chan *chan = vd->tx.chan; + + if (le16_to_cpu(desc->flags) & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); kfree(async_desc); } @@ -1384,6 +1558,7 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->common.device_terminate_all = bam_dma_terminate_all; bdev->common.device_issue_pending = bam_issue_pending; bdev->common.device_tx_status = bam_tx_status; + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; bdev->common.dev = bdev->dev; ret = dma_async_device_register(&bdev->common); diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h index 68fc0e643b1b9..a2594264b0f58 100644 --- a/include/linux/dma/qcom_bam_dma.h +++ b/include/linux/dma/qcom_bam_dma.h @@ -6,6 +6,8 @@ #ifndef _QCOM_BAM_DMA_H #define _QCOM_BAM_DMA_H +#include + #include /* @@ -34,6 +36,18 @@ enum bam_command_type { BAM_READ_COMMAND, }; +/** + * struct bam_desc_metadata - DMA descriptor metadata specific to the BAM driver. + * + * @scratchpad_addr: Physical address to use for dummy write operations when + * queuing command descriptors with LOCK/UNLOCK bits set. + * @direction: Transfer direction of this channel. + */ +struct bam_desc_metadata { + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; +}; + /* * prep_bam_ce_le32 - Wrapper function to prepare a single BAM command * element with the data already in le32 format. From d69e4ce586c348d128778ac31db2cf067eb84e66 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:09 +0200 Subject: [PATCH 0264/1058] crypto: qce - Cancel work on device detach The workqueue is setup in probe() but never cancelled on error or in remove(). Set up a devres action to clean it up. We need to move the initialization earlier as we don't want to cancel the work before any outstanding DMA transfer is terminated. Make sure we do terminate all transfers in qce_dma_release() devres action. Fixes: eb7986e5e14d ("crypto: qce - convert tasklet to workqueue") Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=7 Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-7-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 13 ++++++++++++- drivers/crypto/qce/dma.c | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index b966f3365b7de..f671946cf7351 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -186,6 +186,13 @@ static int qce_check_version(struct qce_device *qce) return 0; } +static void qce_cancel_work(void *data) +{ + struct work_struct *work = data; + + cancel_work_sync(work); +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -227,6 +234,11 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; + INIT_WORK(&qce->done_work, qce_req_done_work); + ret = devm_add_action_or_reset(dev, qce_cancel_work, &qce->done_work); + if (ret) + return ret; + ret = devm_qce_dma_request(qce->dev, &qce->dma); if (ret) return ret; @@ -239,7 +251,6 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - INIT_WORK(&qce->done_work, qce_req_done_work); crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH); qce->async_req_enqueue = qce_async_request_enqueue; diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 68cafd4741ad3..7ec9d72fd690f 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -13,6 +13,8 @@ static void qce_dma_release(void *data) { struct qce_dma_data *dma = data; + dmaengine_terminate_sync(dma->txchan); + dmaengine_terminate_sync(dma->rxchan); dma_release_channel(dma->txchan); dma_release_channel(dma->rxchan); kfree(dma->result_buf); From 3d19132c53fcf5294f625f2b24066582e73bacb0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:10 +0200 Subject: [PATCH 0265/1058] crypto: qce - Include algapi.h in the core.h header The header defines a struct embedding struct crypto_queue whose size needs to be known and which is defined in crypto/algapi.h. Move the inclusion from core.c to core.h. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-8-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 1 - drivers/crypto/qce/core.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index f671946cf7351..ad37c2b8ae53a 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "core.h" diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index eb6fa7a8b64a8..f092ce2d3b04a 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -8,6 +8,7 @@ #include #include +#include #include "dma.h" From 343ddd9edb477c252e686e5bf0d2d218b4e40c00 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:11 +0200 Subject: [PATCH 0266/1058] crypto: qce - Remove unused ignore_buf It's unclear what the purpose of this field is. It has been here since the initial commit but without any explanation. The driver works fine without it. We still keep allocating more space in the result buffer, we just don't need to store its address. While at it: move the QCE_IGNORE_BUF_SZ definition into dma.c as it's not used outside of this compilation unit. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-9-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 4 ++-- drivers/crypto/qce/dma.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 7ec9d72fd690f..d1daa229361aa 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -9,6 +9,8 @@ #include "dma.h" +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) + static void qce_dma_release(void *data) { struct qce_dma_data *dma = data; @@ -43,8 +45,6 @@ int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma) goto error_nomem; } - dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; - return devm_add_action_or_reset(dev, qce_dma_release, dma); error_nomem: diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index 31629185000e1..fc337c435cd14 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -23,7 +23,6 @@ struct qce_result_dump { u32 status2; }; -#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) #define QCE_RESULT_BUF_SZ \ ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE) @@ -31,7 +30,6 @@ struct qce_dma_data { struct dma_chan *txchan; struct dma_chan *rxchan; struct qce_result_dump *result_buf; - void *ignore_buf; }; int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma); From 55dcb67a238b0e3a97ba2c7f588c5188217bde83 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:12 +0200 Subject: [PATCH 0267/1058] crypto: qce - Simplify arguments of devm_qce_dma_request() This function can extract all the information it needs from struct qce_device alone so simplify its arguments. This is done in preparation for adding support for register I/O over DMA which will require accessing even more fields from struct qce_device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-10-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 2 +- drivers/crypto/qce/dma.c | 5 ++++- drivers/crypto/qce/dma.h | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index ad37c2b8ae53a..a0e2eadc3afd5 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -238,7 +238,7 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_qce_dma_request(qce->dev, &qce->dma); + ret = devm_qce_dma_request(qce); if (ret) return ret; diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index d1daa229361aa..d60efb5c26d88 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -7,6 +7,7 @@ #include #include +#include "core.h" #include "dma.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) @@ -22,8 +23,10 @@ static void qce_dma_release(void *data) kfree(dma->result_buf); } -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma) +int devm_qce_dma_request(struct qce_device *qce) { + struct qce_dma_data *dma = &qce->dma; + struct device *dev = qce->dev; int ret; dma->txchan = dma_request_chan(dev, "tx"); diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index fc337c435cd14..483789d9fa98e 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -8,6 +8,8 @@ #include +struct qce_device; + /* maximum data transfer block size between BAM and CE */ #define QCE_BAM_BURST_SIZE 64 @@ -32,7 +34,7 @@ struct qce_dma_data { struct qce_result_dump *result_buf; }; -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma); +int devm_qce_dma_request(struct qce_device *qce); int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, int in_ents, struct scatterlist *sg_out, int out_ents, dma_async_tx_callback cb, void *cb_param); From e503cb9666cf4045a331c3b666fe66a750f1f1d7 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:13 +0200 Subject: [PATCH 0268/1058] crypto: qce - Use existing devres APIs in devm_qce_dma_request() Switch to devm_kmalloc() and devm_dma_alloc_chan() in devm_qce_dma_request(). This allows us to drop two labels and shrink the function. Signed-off-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-11-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index d60efb5c26d88..26347e9fc078a 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -12,49 +12,34 @@ #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) -static void qce_dma_release(void *data) +static void qce_dma_terminate(void *data) { struct qce_dma_data *dma = data; dmaengine_terminate_sync(dma->txchan); dmaengine_terminate_sync(dma->rxchan); - dma_release_channel(dma->txchan); - dma_release_channel(dma->rxchan); - kfree(dma->result_buf); } int devm_qce_dma_request(struct qce_device *qce) { struct qce_dma_data *dma = &qce->dma; struct device *dev = qce->dev; - int ret; - dma->txchan = dma_request_chan(dev, "tx"); + dma->result_buf = devm_kmalloc(dev, QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, GFP_KERNEL); + if (!dma->result_buf) + return -ENOMEM; + + dma->txchan = devm_dma_request_chan(dev, "tx"); if (IS_ERR(dma->txchan)) return dev_err_probe(dev, PTR_ERR(dma->txchan), "Failed to get TX DMA channel\n"); - dma->rxchan = dma_request_chan(dev, "rx"); - if (IS_ERR(dma->rxchan)) { - ret = dev_err_probe(dev, PTR_ERR(dma->rxchan), - "Failed to get RX DMA channel\n"); - goto error_rx; - } - - dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, - GFP_KERNEL); - if (!dma->result_buf) { - ret = -ENOMEM; - goto error_nomem; - } - - return devm_add_action_or_reset(dev, qce_dma_release, dma); + dma->rxchan = devm_dma_request_chan(dev, "rx"); + if (IS_ERR(dma->rxchan)) + return dev_err_probe(dev, PTR_ERR(dma->rxchan), + "Failed to get RX DMA channel\n"); -error_nomem: - dma_release_channel(dma->rxchan); -error_rx: - dma_release_channel(dma->txchan); - return ret; + return devm_add_action_or_reset(dev, qce_dma_terminate, dma); } struct scatterlist * From a76b4c81ae271548c48d8a6e296843dfaec00a18 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:14 +0200 Subject: [PATCH 0269/1058] crypto: qce - Map crypto memory for DMA As the first step in converting the driver to using DMA for register I/O, let's map the crypto memory range. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-12-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 23 ++++++++++++++++++++++- drivers/crypto/qce/core.h | 6 ++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index a0e2eadc3afd5..d7b7a3dda4649 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -192,10 +192,19 @@ static void qce_cancel_work(void *data) cancel_work_sync(work); } +static void qce_crypto_unmap_dma(void *data) +{ + struct qce_device *qce = data; + + dma_unmap_resource(qce->dev, qce->base_dma, qce->dma_size, + DMA_BIDIRECTIONAL, 0); +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct qce_device *qce; + struct resource *res; int ret; qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL); @@ -205,7 +214,7 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->dev = dev; platform_set_drvdata(pdev, qce); - qce->base = devm_platform_ioremap_resource(pdev, 0); + qce->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); @@ -255,6 +264,18 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->async_req_enqueue = qce_async_request_enqueue; qce->async_req_done = qce_async_request_done; + qce->dma_size = resource_size(res); + qce->base_dma = dma_map_resource(dev, res->start, qce->dma_size, + DMA_BIDIRECTIONAL, 0); + qce->base_phys = res->start; + ret = dma_mapping_error(dev, qce->base_dma); + if (ret) + return ret; + + ret = devm_add_action_or_reset(qce->dev, qce_crypto_unmap_dma, qce); + if (ret) + return ret; + return devm_qce_register_algs(qce); } diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index f092ce2d3b04a..a80e12eac6c87 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -27,6 +27,9 @@ * @dma: pointer to dma data * @burst_size: the crypto burst size * @pipe_pair_id: which pipe pair id the device using + * @base_dma: base DMA address + * @base_phys: base physical address + * @dma_size: size of memory mapped for DMA * @async_req_enqueue: invoked by every algorithm to enqueue a request * @async_req_done: invoked by every algorithm to finish its request */ @@ -43,6 +46,9 @@ struct qce_device { struct qce_dma_data dma; int burst_size; unsigned int pipe_pair_id; + dma_addr_t base_dma; + phys_addr_t base_phys; + size_t dma_size; int (*async_req_enqueue)(struct qce_device *qce, struct crypto_async_request *req); void (*async_req_done)(struct qce_device *qce, int ret); From 5add50fc2c2b3b758e7eb11302ce47917846e54f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:15 +0200 Subject: [PATCH 0270/1058] crypto: qce - Add BAM DMA support for crypto register I/O Switch to using BAM DMA for register I/O in addition to passing data. To that end: provide the necessary infrastructure in the driver, modify the ordering of operations as required and replace all direct register writes with wrappers queueing DMA command descriptors. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-13-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/aead.c | 10 +-- drivers/crypto/qce/common.c | 20 +++--- drivers/crypto/qce/dma.c | 120 ++++++++++++++++++++++++++++++++-- drivers/crypto/qce/dma.h | 5 ++ drivers/crypto/qce/sha.c | 10 +-- drivers/crypto/qce/skcipher.c | 10 +-- 6 files changed, 144 insertions(+), 31 deletions(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 9cb11fada2c4d..8831adb7b0f56 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -463,17 +463,17 @@ qce_aead_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } - ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, - qce_aead_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_src; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, + qce_aead_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 54a78a57f6302..37bb6f03244d3 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -25,7 +25,7 @@ static inline u32 qce_read(struct qce_device *qce, u32 offset) static inline void qce_write(struct qce_device *qce, u32 offset, u32 val) { - writel(val, qce->base + offset); + qce_write_dma(qce, offset, val); } static inline void qce_write_array(struct qce_device *qce, u32 offset, @@ -82,6 +82,8 @@ static void qce_setup_config(struct qce_device *qce) { u32 config; + qce_clear_bam_transaction(qce); + /* get big endianness */ config = qce_config_reg(qce, 0); @@ -90,12 +92,14 @@ static void qce_setup_config(struct qce_device *qce) qce_write(qce, REG_CONFIG, config); } -static inline void qce_crypto_go(struct qce_device *qce, bool result_dump) +static inline int qce_crypto_go(struct qce_device *qce, bool result_dump) { if (result_dump) qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); else qce_write(qce, REG_GOPROC, BIT(GO_SHIFT)); + + return qce_submit_cmd_desc(qce); } #if defined(CONFIG_CRYPTO_DEV_QCE_SHA) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD) @@ -223,9 +227,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -386,9 +388,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -535,9 +535,7 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) qce_write(qce, REG_CONFIG, config); /* Start the process */ - qce_crypto_go(qce, !IS_CCM(flags)); - - return 0; + return qce_crypto_go(qce, !IS_CCM(flags)); } #endif diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 26347e9fc078a..1b43c56503334 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include @@ -11,6 +13,96 @@ #include "dma.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) +#define QCE_BAM_CMD_SGL_SIZE 128 +#define QCE_BAM_CMD_ELEMENT_SIZE 128 + +struct qce_desc_info { + struct dma_async_tx_descriptor *dma_desc; + enum dma_data_direction dir; +}; + +struct qce_bam_transaction { + struct bam_cmd_element bam_ce[QCE_BAM_CMD_ELEMENT_SIZE]; + struct scatterlist wr_sgl[QCE_BAM_CMD_SGL_SIZE]; + struct qce_desc_info *desc; + u32 bam_ce_idx; + u32 pre_bam_ce_idx; + u32 wr_sgl_cnt; +}; + +void qce_clear_bam_transaction(struct qce_device *qce) +{ + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + + bam_txn->bam_ce_idx = 0; + bam_txn->wr_sgl_cnt = 0; + bam_txn->pre_bam_ce_idx = 0; +} + +int qce_submit_cmd_desc(struct qce_device *qce) +{ + struct qce_desc_info *qce_desc = qce->dma.bam_txn->desc; + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + struct dma_async_tx_descriptor *dma_desc; + struct dma_chan *chan = qce->dma.rxchan; + unsigned long attrs = DMA_PREP_CMD; + dma_cookie_t cookie; + unsigned int mapped; + int ret; + + mapped = dma_map_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + if (!mapped) + return -ENOMEM; + + dma_desc = dmaengine_prep_slave_sg(chan, bam_txn->wr_sgl, mapped, DMA_MEM_TO_DEV, attrs); + if (!dma_desc) { + ret = -ENOMEM; + goto err_unmap_sg; + } + + qce_desc->dma_desc = dma_desc; + cookie = dmaengine_submit(qce_desc->dma_desc); + + ret = dma_submit_error(cookie); + if (ret) + goto err_unmap_sg; + + return 0; + +err_unmap_sg: + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + return ret; +} + +static void qce_prep_dma_cmd_desc(struct qce_device *qce, struct qce_dma_data *dma, + unsigned int addr, void *buf) +{ + struct qce_bam_transaction *bam_txn = dma->bam_txn; + struct bam_cmd_element *bam_ce_buf; + int bam_ce_size, cnt, idx; + + idx = bam_txn->bam_ce_idx; + bam_ce_buf = &bam_txn->bam_ce[idx]; + bam_prep_ce_le32(bam_ce_buf, addr, BAM_WRITE_COMMAND, *((__le32 *)buf)); + + bam_ce_buf = &bam_txn->bam_ce[bam_txn->pre_bam_ce_idx]; + bam_txn->bam_ce_idx++; + bam_ce_size = (bam_txn->bam_ce_idx - bam_txn->pre_bam_ce_idx) * sizeof(*bam_ce_buf); + + cnt = bam_txn->wr_sgl_cnt; + + sg_set_buf(&bam_txn->wr_sgl[cnt], bam_ce_buf, bam_ce_size); + + ++bam_txn->wr_sgl_cnt; + bam_txn->pre_bam_ce_idx = bam_txn->bam_ce_idx; +} + +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val) +{ + unsigned int reg_addr = ((unsigned int)(qce->base_phys) + offset); + + qce_prep_dma_cmd_desc(qce, &qce->dma, reg_addr, &val); +} static void qce_dma_terminate(void *data) { @@ -39,6 +131,16 @@ int devm_qce_dma_request(struct qce_device *qce) return dev_err_probe(dev, PTR_ERR(dma->rxchan), "Failed to get RX DMA channel\n"); + dma->bam_txn = devm_kzalloc(dev, sizeof(*dma->bam_txn), GFP_KERNEL); + if (!dma->bam_txn) + return -ENOMEM; + + dma->bam_txn->desc = devm_kzalloc(dev, sizeof(*dma->bam_txn->desc), GFP_KERNEL); + if (!dma->bam_txn->desc) + return -ENOMEM; + + sg_init_table(dma->bam_txn->wr_sgl, QCE_BAM_CMD_SGL_SIZE); + return devm_add_action_or_reset(dev, qce_dma_terminate, dma); } @@ -98,28 +200,36 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg, { struct dma_chan *rxchan = dma->rxchan; struct dma_chan *txchan = dma->txchan; - unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long txflags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long rxflags = txflags | DMA_PREP_FENCE; int ret; - ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV, + ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, rxflags, DMA_MEM_TO_DEV, NULL, NULL); if (ret) return ret; - return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM, + return qce_dma_prep_sg(txchan, tx_sg, tx_nents, txflags, DMA_DEV_TO_MEM, cb, cb_param); } void qce_dma_issue_pending(struct qce_dma_data *dma) { - dma_async_issue_pending(dma->rxchan); dma_async_issue_pending(dma->txchan); + dma_async_issue_pending(dma->rxchan); } int qce_dma_terminate_all(struct qce_dma_data *dma) { + struct qce_device *qce = container_of(dma, struct qce_device, dma); + struct qce_bam_transaction *bam_txn = dma->bam_txn; int ret; ret = dmaengine_terminate_all(dma->rxchan); - return ret ?: dmaengine_terminate_all(dma->txchan); + if (ret) + return ret; + + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + + return dmaengine_terminate_all(dma->txchan); } diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index 483789d9fa98e..f05dfa9e6b25b 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -8,6 +8,7 @@ #include +struct qce_bam_transaction; struct qce_device; /* maximum data transfer block size between BAM and CE */ @@ -32,6 +33,7 @@ struct qce_dma_data { struct dma_chan *txchan; struct dma_chan *rxchan; struct qce_result_dump *result_buf; + struct qce_bam_transaction *bam_txn; }; int devm_qce_dma_request(struct qce_device *qce); @@ -43,5 +45,8 @@ int qce_dma_terminate_all(struct qce_dma_data *dma); struct scatterlist * qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, unsigned int max_len); +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val); +int qce_submit_cmd_desc(struct qce_device *qce); +void qce_clear_bam_transaction(struct qce_device *qce); #endif /* _DMA_H_ */ diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 1b37121cbcdcb..508b4c18d2119 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -109,17 +109,17 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req) goto error_unmap_src; } - ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, - &rctx->result_sg, 1, qce_ahash_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_dst; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, + &rctx->result_sg, 1, qce_ahash_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index db0b648a56eb1..78fe3c3611cfe 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -142,18 +142,18 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } + ret = qce_start(async_req, tmpl->crypto_alg_type); + if (ret) + goto error_unmap_src; + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, qce_skcipher_done, async_req); if (ret) - goto error_unmap_src; + goto error_terminate; qce_dma_issue_pending(&qce->dma); - ret = qce_start(async_req, tmpl->crypto_alg_type); - if (ret) - goto error_terminate; - return 0; error_terminate: From c36112e9987659986a3171f206e4c4a05932fb8b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:16 +0200 Subject: [PATCH 0271/1058] crypto: qce - Communicate the base physical address to the dmaengine In order to communicate to the BAM DMA engine which address should be used as a scratchpad for dummy writes related to BAM pipe locking, fill out and attach the provided metadata struct to the descriptor. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-14-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 1b43c56503334..6410f8dc5bcf5 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -11,6 +11,7 @@ #include "core.h" #include "dma.h" +#include "regs-v5.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) #define QCE_BAM_CMD_SGL_SIZE 128 @@ -41,6 +42,10 @@ void qce_clear_bam_transaction(struct qce_device *qce) int qce_submit_cmd_desc(struct qce_device *qce) { + struct bam_desc_metadata meta = { + .scratchpad_addr = qce->base_phys + REG_VERSION, + .direction = DMA_MEM_TO_DEV, + }; struct qce_desc_info *qce_desc = qce->dma.bam_txn->desc; struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; struct dma_async_tx_descriptor *dma_desc; @@ -60,15 +65,21 @@ int qce_submit_cmd_desc(struct qce_device *qce) goto err_unmap_sg; } + ret = dmaengine_desc_attach_metadata(dma_desc, &meta, sizeof(meta)); + if (ret) + goto err_free_desc; + qce_desc->dma_desc = dma_desc; cookie = dmaengine_submit(qce_desc->dma_desc); ret = dma_submit_error(cookie); if (ret) - goto err_unmap_sg; + goto err_free_desc; return 0; +err_free_desc: + dmaengine_desc_free(dma_desc); err_unmap_sg: dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); return ret; From 5e684f04c993e0936142aa70868eedac9488a1c4 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 29 May 2025 17:06:00 +0530 Subject: [PATCH 0272/1058] QCLINUX: defconfig: Introduce prune.config fragment Add prune.config fragment to disable support for non-Qualcomm architectures. This helps reduce boot image size and improves kernel build KPIs by trimming unnecessary configuration options. Signed-off-by: Komal Bajaj --- arch/arm64/configs/prune.config | 403 ++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 arch/arm64/configs/prune.config diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config new file mode 100644 index 0000000000000..aa4f210106bac --- /dev/null +++ b/arch/arm64/configs/prune.config @@ -0,0 +1,403 @@ +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BCMBCA is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BLAIZE is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_NXP is not set +# CONFIG_ARCH_MA35 is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_TESLA_FSD is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_MOUSE_PS2 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +# CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MRVL_SDIO is not set +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCIE_ALTERA_MSI is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCI_MESON is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_GNSS_MTK_SERIAL is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_BRCMNAND_BCMBCA is not set +# CONFIG_MTD_NAND_BRCMNAND_BRCMSTB is not set +# CONFIG_MTD_NAND_BRCMNAND_IPROC is not set +# CONFIG_B53_SRAB_DRIVER is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_MACB is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +# CONFIG_HNS3_HCLGE is not set +# CONFIG_HNS3_ENET is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_MVMDIO is not set +# CONFIG_SKY2 is not set +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLX5_CORE_EN is not set +# CONFIG_R8169 is not set +# CONFIG_SMC91X is not set +# CONFIG_SMSC911X is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_CAN_MCP251XFD is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_MWIFIEX is not set +# CONFIG_MWIFIEX_SDIO is not set +# CONFIG_MWIFIEX_PCIE is not set +# CONFIG_MT7921E is not set +# CONFIG_WL18XX is not set +# CONFIG_WLCORE_SDIO is not set +# CONFIG_KEYBOARD_CROS_EC is not set +# CONFIG_KEYBOARD_MTK_PMIC is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_INPUT_TPS65219_PWRBUTTON is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LPUART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE is not set +# CONFIG_TCG_TIS_SPI_CR50 is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_CROS_EC_TUNNEL is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_DW_DMA is not set +# CONFIG_SPI_DW_MMIO is not set +# CONFIG_PINCTRL_MAX77620 is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_BD9571MWV is not set +# CONFIG_GPIO_MAX77620 is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MT6360 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_PM8916_WATCHDOG is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_RK8XX_I2C is not set +# CONFIG_MFD_RK8XX_SPI is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TPS65219 is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_REGULATOR_AXP20X is not set +# CONFIG_REGULATOR_BD718XX is not set +# CONFIG_REGULATOR_BD9571MWV is not set +# CONFIG_REGULATOR_CROS_EC is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_HI6421V530 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_MT6357 is not set +# CONFIG_REGULATOR_MT6358 is not set +# CONFIG_REGULATOR_MT6359 is not set +# CONFIG_REGULATOR_MT6360 is not set +# CONFIG_REGULATOR_MT6397 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX412 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_ADV7511_AUDIO is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_EASRC is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_DA7213 is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5659 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIMPLE_MUX is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_GADGET is not set +# CONFIG_USB_CDNS3_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_CHIPIDEA_UDC is not set +# CONFIG_USB_CHIPIDEA_HOST is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_TYPEC_FUSB302 is not set +# CONFIG_UCSI_CCG is not set +# CONFIG_TYPEC_TPS6598X is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDHCI_AM654 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX77686 is not set +# CONFIG_RTC_DRV_RK808 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_S5M is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_CROS_EC is not set +# CONFIG_RTC_DRV_MT6397 is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_VIDEO_MAX96712 is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CROS_EC is not set +# CONFIG_CROS_EC_I2C is not set +# CONFIG_CROS_EC_RPMSG is not set +# CONFIG_CROS_EC_SPI is not set +# CONFIG_CROS_EC_CHARDEV is not set +# CONFIG_CLK_VEXPRESS_OSC is not set +# CONFIG_COMMON_CLK_RK808 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_S2MPS11 is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_BD718XX is not set +# CONFIG_SOC_TI is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_USBC_CROS_EC is not set +# CONFIG_MAX9611 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_AM335X_ADC is not set +# CONFIG_IIO_CROS_EC_SENSORS_CORE is not set +# CONFIG_IIO_CROS_EC_SENSORS is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_CROS_EC_LIGHT_PROX is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_VCNL4000 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_IIO_CROS_EC_BARO is not set +# CONFIG_MPL3115 is not set +# CONFIG_PWM_CROS_EC is not set +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC2 is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_HISI_HPRE is not set +# CONFIG_CRYPTO_DEV_HISI_TRNG is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +# CONFIG_DEVMEM is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DEVELOP is not set +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +# CONFIG_AUDIT_GENERIC is not set +# CONFIG_EFI_DISABLE_RUNTIME is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set From 4b4c046ab9718346523faceb3df8bcccbcc2615b Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 23 Sep 2025 14:20:27 +0530 Subject: [PATCH 0273/1058] QCLINUX: arch: arm64: configs: Define qcom.config and enable DMABUF heaps The `qcom.config` file serves as a Qualcomm-specific kernel configuration fragment used to enable features required by Qualcomm SoCs. It helps ensure that essential features and subsystems required by Qualcomm platforms are enabled. This initial version of `qcom.config` enables DMABUF heap support, including the system heap and default CMA heap. These configurations are essential for buffer sharing across subsystems such as camera, display, and DSP on Qualcomm platforms like qcs6490. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm64/configs/qcom.config diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config new file mode 100644 index 0000000000000..f5164133e8930 --- /dev/null +++ b/arch/arm64/configs/qcom.config @@ -0,0 +1,3 @@ +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y From 1b5de658aa1ce433cc2bdf4a547853d7398aab24 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 26 Sep 2025 10:08:11 +0800 Subject: [PATCH 0274/1058] QCLINUX:arch: arm64: configs: Enable coresight components in qcom.config Add Coresight configs to enable Coresight device drivers on mainline. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f5164133e8930..895e933b8ac85 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -1,3 +1,9 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_CORESIGHT_TPDM=m +CONFIG_CORESIGHT_DUMMY=m +CONFIG_CORESIGHT_CTCU=m +CONFIG_CORESIGHT_SOURCE_ETM4X=m +CONFIG_CORESIGHT_TGU=m +CONFIG_CORESIGHT_CORESIGHT_TNOC=m From bd27ccb43fffec1a5d27250efe0fd71c222ae11f Mon Sep 17 00:00:00 2001 From: Charan Teja Kalla Date: Tue, 30 Sep 2025 18:27:55 +0530 Subject: [PATCH 0275/1058] QCLINUX: defconfig: enable zram defconfig on qcom.config Enable ZRAM defconfig on qcom.config. This empowers users to use the compressed block devices for usecases, eg: swap device on zram. Tested: make ARCH=arm64 menuconfig defconfig qcom.config, booted with this configuration on QEMU and verified if /dev/zram0 is exist. Signed-off-by: Charan Teja Kalla --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 895e933b8ac85..d088c252c0756 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -7,3 +7,4 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_ZRAM=y From 99e082c0eb8e320dbc463ff7e7c8d9c998aa2f4d Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 6 Oct 2025 16:56:58 +0530 Subject: [PATCH 0276/1058] QCLINUX: defconfig: Enable scheduler and thermal related configs Enabled key configs for thermal management (CPU_IDLE_THERMAL, IDLE_INJECT), scheduler (SCHED_DEBUG, SCHEDSTATS, TRACE_MMIO_ACCESS), and power control (POWERCAP, UCLAMP_TASK). Also enabled KPROBES, PAN emulation and watchdog pretimeout panic governor for improved instrumentation and security. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d088c252c0756..971dbb2b486bc 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -1,10 +1,33 @@ -CONFIG_DMABUF_HEAPS=y -CONFIG_DMABUF_HEAPS_SYSTEM=y -CONFIG_DMABUF_HEAPS_CMA=y -CONFIG_CORESIGHT_TPDM=m +# qcom.config for Qualcomm-specific kernel configuration +# +# $ make ARCH=arm64 defconfig qcom.config +# +# Keep alphabetically sorted +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m -CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_THERMAL=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_IDLE_INJECT=y +CONFIG_KPROBES=y +CONFIG_POWERCAP=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TRACE_MMIO_ACCESS=y +CONFIG_UCLAMP_TASK_GROUP=y +CONFIG_UCLAMP_TASK=y +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y From c1bdbd915180c7b7dbcc629f738541abc8e7491d Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 6 Oct 2025 17:11:01 +0530 Subject: [PATCH 0277/1058] QCLINUX: debug: Enable additional Qualcomm-specific debug configs Enabled various debug-related kernel config options to improve system diagnostics and aid in development and issue analysis. Signed-off-by: Komal Bajaj --- kernel/configs/debug.config | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 307c97ac5fa9c..2df1c1bd8106f 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -116,3 +116,12 @@ CONFIG_FUNCTION_TRACER=y # CONFIG_DEBUG_PREEMPT=y CONFIG_PREEMPT=y + +# +# Qualcomm Debug Configs +# +CONFIG_CMA_DEBUG=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_PAGEALLOC=y +# CONFIG_FW_LOADER_DEBUG is not set +CONFIG_HARDLOCKUP_DETECTOR=y From 6a388270e649ed75e0151c25b3660a381d824dfb Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 31 Oct 2025 15:58:40 +0800 Subject: [PATCH 0278/1058] QCLINUX: arch: arm64: configs: Enable stm components in qcom.config Add STM configs to enable STM functions, like stm ftrace and stm heartbeat. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 971dbb2b486bc..a05f6e73a8979 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -21,6 +21,11 @@ CONFIG_KPROBES=y CONFIG_POWERCAP=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_SYS_T=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m +CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 5970d428aef7810cc95cf128adff5f71934302b2 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Tue, 4 Nov 2025 17:35:07 +0800 Subject: [PATCH 0279/1058] QCLINUX: defconfig: enable Crypto and ICE related configs Enabled key config of Crypto (CONFIG_CRYPTO_USER_API, CONFIG_CRYPTO_USER_API_HASH, CONFIG_CRYPTO_USER_API_SKCIPHER, CONFIG_CRYPTO_USER_API_AEAD). And else for support ICE config. Signed-off-by: Wenjia Zhang --- arch/arm64/configs/qcom.config | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a05f6e73a8979..aeed65c8c6726 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -36,3 +36,20 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y + +# Add config to support Crypto and ICE +CONFIG_SCSI_UFS_QCOM=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT_FALLBACK=y +CONFIG_FS_ENCRYPTION_HW_WRAPPED_KEYS=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_QCOM_INLINE_CRYPTO_ENGINE=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_BLK_INLINE_ENCRYPTION_HW_WRAPPED_KEYS=y + From 2340f15f24bea1f2cc7dcc579cb578ad2edb010e Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Wed, 5 Nov 2025 14:26:27 +0530 Subject: [PATCH 0280/1058] QCLINUX: defconfig: enable amc6821 defconfig on qcom.config Enable SENSOR_AMC6821 defconfig to enable fan controller support. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index aeed65c8c6726..33faf8d7aa8f2 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_STM_PROTO_SYS_T=m CONFIG_STM_SOURCE_CONSOLE=m CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m +CONFIG_SENSORS_AMC6821=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 0ff483eb743eef30c36289eee0aa98fd4c1187e0 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Thu, 13 Nov 2025 14:59:19 +0530 Subject: [PATCH 0281/1058] QCLINUX: defconfig: Enable QCA808X ethernet phy config Enable the config for the QCA808X ethernet PHY driver. Ethernet is non functional without this driver on Lemans and Monaco EVK. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 33faf8d7aa8f2..d8fec6c2b60cc 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -19,6 +19,7 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y +CONFIG_QCA808X_PHY=m CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From 6c2b743aa1b753f3a0d6616a5ab259846015d06b Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 14 Nov 2025 19:08:45 +0530 Subject: [PATCH 0282/1058] QCLINUX: defconfig: Enable EDAC_QCOM on qcom.config Enable QCOM EDAC driver support for QCOM SoCs. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d8fec6c2b60cc..789824130df2b 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -16,6 +16,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_EDAC_QCOM=m CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y From e5873d9f03bcaa5478d420526ae26983f4769094 Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 12 Nov 2025 11:29:07 +0800 Subject: [PATCH 0283/1058] QCLINUX: debug: Enable WLAN related debug configs Enable WLAN related debug configs. Signed-off-by: Yingying Tang --- kernel/configs/debug.config | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 2df1c1bd8106f..2b19e5e651cb9 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -120,8 +120,31 @@ CONFIG_PREEMPT=y # # Qualcomm Debug Configs # +CONFIG_ATH11K_COREDUMP=y +CONFIG_ATH11K_DEBUG=y +CONFIG_ATH11K_DEBUGFS=y +CONFIG_ATH11K_TRACING=y +CONFIG_ATH12K_DEBUG=y +CONFIG_ATH12K_DEBUGFS=y +CONFIG_ATH12K_TRACING=y +CONFIG_ATH12K_COREDUMP=y +CONFIG_CFG80211_DEBUGFS=y CONFIG_CMA_DEBUG=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_FUNCTION_GRAPH_TRACER=y # CONFIG_FW_LOADER_DEBUG is not set CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_KPROBE_EVENTS=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_NL80211_TESTMODE=y +CONFIG_PREEMPT_TRACER=y +CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_TRACEPOINTS=y +CONFIG_TRACING=y +CONFIG_UPROBE_EVENTS=y From 02ea8022fd0ea2ab7d94c28895292f29354e1edd Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 12 Nov 2025 12:01:17 +0800 Subject: [PATCH 0284/1058] QCLINUX: defconfig: Enable ATH reg setting Enable ATH reg setting, then user can change country code by netlink command. Signed-off-by: Yingying Tang --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 789824130df2b..d7c07deb1b734 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,6 +4,8 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m @@ -17,6 +19,7 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m +CONFIG_EXPERT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y From a99eb0648291544c5203e92cecb0ba7162448d33 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 19 Nov 2025 19:55:44 +0530 Subject: [PATCH 0285/1058] QCLINUX: defconfig: Enable BT_RFCOMM, BT_BNEP and UHID Enable as modules the BT_BNEP and BT_RFCOMM drivers which are required for Bluetooth profiles such as PAN and SPP. Without these modules, PAN and SPP functionality will not be available. Enable UHID support to allow HID over GATT operations. Without this, user-space cannot create virtual HID devices, which impacts HID profile usage over Bluetooth. Signed-off-by: Wei Deng --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d7c07deb1b734..78a71da640ba3 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -5,6 +5,11 @@ # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m @@ -35,6 +40,7 @@ CONFIG_SENSORS_AMC6821=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y +CONFIG_UHID=m # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From 4dc2bd9dfd4b8e57811c6061e5e35717891670ff Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 21 Nov 2025 10:01:00 +0530 Subject: [PATCH 0286/1058] QCLINUX: defconfig: Enable various power management configs Enable various PM configs to enable suspend-resume. Signed-off-by: Maulik Shah --- arch/arm64/configs/qcom.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 78a71da640ba3..b6cbf9774fc02 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -27,6 +27,13 @@ CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM=y CONFIG_POWERCAP=y CONFIG_QCA808X_PHY=m CONFIG_SCHED_DEBUG=y From fa657c6c28f2077be02f431e6c6ccb40564c2358 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 21 Nov 2025 13:32:46 +0530 Subject: [PATCH 0287/1058] QCLINUX: debug: Enable power management debug configs Enabled various power management debug related kernel config options to improve system diagnostics and aid in development and issue analysis. Signed-off-by: Maulik Shah --- kernel/configs/debug.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 2b19e5e651cb9..8579fc7f0d69a 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -143,6 +143,9 @@ CONFIG_MAC80211_DEBUGFS=y CONFIG_NL80211_TESTMODE=y CONFIG_PREEMPT_TRACER=y CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_PM_DEBUG=y +CONFIG_PM_SLEEP_DEBUG=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y CONFIG_TRACEPOINTS=y From 43e7ec6d3e178c84f2f8c9b1576ae81152cd579b Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 27 Nov 2025 15:03:55 +0530 Subject: [PATCH 0288/1058] QCLINUX: Revert "QCLINUX: defconfig: enable Crypto and ICE related configs" Revert commit 68f6c9a13767b281d3859caf834fbdd3c027ee22. Enabling ICE-related configurations causes crashes on the lemans-evk device, so this change is being reverted until the issue is resolved. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index b6cbf9774fc02..0ed1640e64146 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -55,20 +55,3 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y - -# Add config to support Crypto and ICE -CONFIG_SCSI_UFS_QCOM=y -CONFIG_CRYPTO_USER_API=y -CONFIG_CRYPTO_USER_API_HASH=y -CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_CRYPTO_USER_API_AEAD=y -CONFIG_BLK_INLINE_ENCRYPTION=y -CONFIG_FS_ENCRYPTION=y -CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y -CONFIG_FS_ENCRYPTION_INLINE_CRYPT_FALLBACK=y -CONFIG_FS_ENCRYPTION_HW_WRAPPED_KEYS=y -CONFIG_SCSI_UFS_CRYPTO=y -CONFIG_QCOM_INLINE_CRYPTO_ENGINE=y -CONFIG_CRYPTO_DEV_QCOM_ICE=y -CONFIG_BLK_INLINE_ENCRYPTION_HW_WRAPPED_KEYS=y - From 886939e9cb0b7ae32af7c143a79220bfc14190df Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 27 Nov 2025 19:01:13 +0530 Subject: [PATCH 0289/1058] QCLINUX: prune.config: Remove CONFIG_IGB prune entry Dropped '# CONFIG_IGB is not set' from prune.config. This allows dependent config CONFIG_I2C, to be enabled via base defconfig, fixing missing /dev/i2c-* devices. Signed-off-by: Komal Bajaj --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index aa4f210106bac..9fc201d4eb924 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -86,7 +86,6 @@ # CONFIG_HNS3_ENET is not set # CONFIG_E1000 is not set # CONFIG_E1000E is not set -# CONFIG_IGB is not set # CONFIG_IGBVF is not set # CONFIG_MVMDIO is not set # CONFIG_SKY2 is not set From a570d45e2954aa87f89ab786cdf250633c642ad0 Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Thu, 27 Nov 2025 15:15:16 +0530 Subject: [PATCH 0290/1058] QCLINUX: defconfig: Enable watchdog drivers for VM usecases CrosVM supports vCPU Stall watchdog. QEMU supports I6300 ESB watchdog. Enable corresponding drivers for Guest VM usecases. Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0ed1640e64146..3e203060de6e6 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -25,6 +25,7 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_PM_SLEEP=y @@ -48,6 +49,7 @@ CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m +CONFIG_VCPU_STALL_DETECTOR=y # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From cf53b09d11458a9587973650ff83daae3f98aece Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 28 Nov 2025 12:38:09 +0530 Subject: [PATCH 0291/1058] QCLINUX: debug.config: Drop heavy debug configs Removed UBSAN, KASAN, kmemleak, lock proving, and function tracing from debug.config to reduce bootup time and prevent probe deferring issues. Signed-off-by: Komal Bajaj --- kernel/configs/debug.config | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 8579fc7f0d69a..6a9237a66deb7 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -32,12 +32,12 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS_ALLOW_ALL=y CONFIG_DEBUG_IRQFLAGS=y -CONFIG_UBSAN=y -CONFIG_UBSAN_BOOL=y -CONFIG_UBSAN_BOUNDS=y -CONFIG_UBSAN_ENUM=y -CONFIG_UBSAN_SHIFT=y -CONFIG_UBSAN_UNREACHABLE=y +# CONFIG_UBSAN is not set +# CONFIG_UBSAN_BOOL is not set +# CONFIG_UBSAN_BOUNDS is not set +# CONFIG_UBSAN_ENUM is not set +# CONFIG_UBSAN_SHIFT is not set +# CONFIG_UBSAN_UNREACHABLE is not set # # Networking Debugging # @@ -56,8 +56,8 @@ CONFIG_DEBUG_NET=y # CONFIG_SLUB_STATS is not set CONFIG_PAGE_EXTENSION=y CONFIG_PAGE_OWNER=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_DEBUG_OBJECTS_FREE=y @@ -72,10 +72,10 @@ CONFIG_DEBUG_VM=y CONFIG_DEBUG_VM_PGFLAGS=y CONFIG_DEBUG_VM_RB=y CONFIG_DEBUG_VM_VMACACHE=y -CONFIG_KASAN=y -CONFIG_KASAN_GENERIC=y -CONFIG_KASAN_INLINE=y -CONFIG_KASAN_VMALLOC=y +# CONFIG_KASAN is not set +# CONFIG_KASAN_GENERIC is not set +# CONFIG_KASAN_INLINE is not set +# CONFIG_KASAN_VMALLOC is not set CONFIG_PTDUMP_DEBUGFS=y CONFIG_SCHED_STACK_END_CHECK=y CONFIG_SLUB_DEBUG_ON=y @@ -93,7 +93,7 @@ CONFIG_SOFTLOCKUP_DETECTOR=y # Lock Debugging (spinlocks, mutexes, etc...) # # CONFIG_PROVE_RAW_LOCK_NESTING is not set -CONFIG_PROVE_LOCKING=y +# CONFIG_PROVE_LOCKING is not set # # Debug kernel data structures # @@ -101,16 +101,16 @@ CONFIG_BUG_ON_DATA_CORRUPTION=y # # RCU Debugging # -CONFIG_RCU_EXPERT=y -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_LIST=y +# CONFIG_RCU_EXPERT is not set +# CONFIG_PROVE_RCU is not set +# CONFIG_PROVE_RCU_LIST is not set # # Tracers # CONFIG_BRANCH_PROFILE_NONE=y CONFIG_DYNAMIC_FTRACE=y CONFIG_FTRACE=y -CONFIG_FUNCTION_TRACER=y +# CONFIG_FUNCTION_TRACER is not set # # Preemption # From 2d3cd429bedfa060e340ff3205569c7cf500143a Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Thu, 20 Nov 2025 15:11:23 +0530 Subject: [PATCH 0292/1058] QCLINUX: defconfig: Enable support for vhost-net, vsock Added the required configs to enable host kernel accelerator for virtio net(vhost-net) and virtual socket protocol(vsock). Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3e203060de6e6..d32f4bbf00f96 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,8 @@ CONFIG_EXPERT=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_PM_AUTOSLEEP=y @@ -50,6 +52,11 @@ CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m CONFIG_VCPU_STALL_DETECTOR=y +CONFIG_VHOST_NET=y +CONFIG_VHOST_VSOCK=y +CONFIG_VSOCKETS=y +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From c6e5c348e32c9fb18f8028928bed1b00d46fdc22 Mon Sep 17 00:00:00 2001 From: Ravi Hothi Date: Mon, 27 Apr 2026 15:11:31 +0530 Subject: [PATCH 0293/1058] FROMLIST: arm64: defconfig: Enable Sound DMIC driver Enable CONFIG_SND_SOC_DMIC as a module in the arm64 defconfig to support digital microphone functionality on Qualcomm's Monaco and Lemans platforms. Link: https://lore.kernel.org/r/20260427094131.607583-1-ravi.hothi@oss.qualcomm.com Reviewed-by: Krzysztof Kozlowski Signed-off-by: Ravi Hothi --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc5..919553fbf5f48 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1132,6 +1132,7 @@ CONFIG_SND_SOC_TEGRA210_AMX=m CONFIG_SND_SOC_TEGRA210_ADX=m CONFIG_SND_SOC_TEGRA210_MIXER=m CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m +CONFIG_SND_SOC_DMIC=m CONFIG_SND_SOC_J721E_EVM=m CONFIG_SND_SOC_XILINX_I2S=m CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=m From 465527013c67485cb1315e6490d9bd2365cb7b21 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 4 Dec 2025 18:20:29 +0530 Subject: [PATCH 0294/1058] QCLINUX: arm64: configs: qcom.config: Enable GUNYAH_WATCHDOG Enable Gunyah watchdog driver for rb3gen2. Signed-off-by: Shivendra Pratap --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d32f4bbf00f96..702ee1b90a607 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -25,6 +25,7 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_GUNYAH_WATCHDOG=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y From 0c0db6c59df7417b0dc182a238beb5011d4f329e Mon Sep 17 00:00:00 2001 From: Raghavender Reddy Bujala Date: Wed, 10 Dec 2025 16:16:53 +0530 Subject: [PATCH 0295/1058] QCLINUX: arm64: configs: qcom.config: Enable UINPUT Enable UINPUT, which is required for BT AVRC profile to register the events and All passthrough commands of AVRCP will be listed in this event under /dev/input/ Signed-off-by: Raghavender Reddy Bujala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 702ee1b90a607..dd67da6c25f7a 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,7 @@ CONFIG_EXPERT=y CONFIG_GUNYAH_WATCHDOG=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y +CONFIG_INPUT_UINPUT=y CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y From 5eaced1aeb41c88a9f14ec06f6c2a6b740f8744f Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Mon, 15 Dec 2025 12:37:54 +0530 Subject: [PATCH 0296/1058] QCLINUX: defconfig: enable EMC2305 defconfig on qcom.config Enable SENSOR_EMC2305 defconfig to enable fan controller support. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index dd67da6c25f7a..28c53bd2fbc51 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -49,6 +49,7 @@ CONFIG_STM_SOURCE_CONSOLE=m CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y +CONFIG_SENSORS_EMC2305=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 9625f0c1a91cdd611b10b85bb2a7f62c4129e185 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 17 Dec 2025 18:42:40 +0530 Subject: [PATCH 0297/1058] QCLINUX: arm64: configs: Added new rt.config for RT kernel Enabled PREEMPT_RT in new rt.config to enable RT kernel features. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/rt.config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm64/configs/rt.config diff --git a/arch/arm64/configs/rt.config b/arch/arm64/configs/rt.config new file mode 100644 index 0000000000000..ca92615d38a17 --- /dev/null +++ b/arch/arm64/configs/rt.config @@ -0,0 +1,3 @@ +# rt.config for Real time kernel features +CONFIG_EXPERT=y +CONFIG_PREEMPT_RT=y From a84f83b49579d4ed040a671bae6136d94ad59556 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Thu, 11 Dec 2025 16:41:21 +0530 Subject: [PATCH 0298/1058] QCLINUX: arm64: configs: qcom.config: Enable I2C_QCOM_GENI as built-in On Lemans and Monaco EVK platforms the boot-from-SD-card feature requires an IO expander to be enabled at an early stage to detect the SD card. This IO expander is connected over I2C. Currently the I2C driver is built as a loadable module which resides on the SD card along with other modules. This creates a circular dependency where to detect the SD card the IO expander must be initialized the IO expander depends on the I2C driver and the I2C driver is on the SD card which cannot be accessed until detection succeeds. To break this dependency enable I2C_QCOM_GENI as built-in so that the driver is available during early boot. Signed-off-by: Viken Dadhaniya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 28c53bd2fbc51..b49d58563974f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_GUNYAH_WATCHDOG=y +CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_INPUT_UINPUT=y From aaa0e9fd7ab7f0cc600601c4582599180117fbfb Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 18 Dec 2025 15:10:56 +0530 Subject: [PATCH 0299/1058] QCLINUX: arm64: configs: Added Kubernetes support in qcom.config Adding config options for Kubernetes support in qcom.config Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index b49d58563974f..a5cd0552d921b 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -68,3 +68,13 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y + +# Kubernetes support +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_FAVOR_DYNMODS=y +CONFIG_IPC_NS=y +CONFIG_NAMESPACES=y +CONFIG_NET_NS=y +CONFIG_PID_NS=y +CONFIG_UTS_NS=y + From 1c52bcfba3b7f3d84825370176c723e648043985 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 23 Dec 2025 17:07:14 +0530 Subject: [PATCH 0300/1058] QCLINUX: qcom.comfig: disable ICE/UFS crypto RB3GEN2 on v6.19-rc2 crashes in qcom_ice_probe() and fails to boot. Disable inline crypto (ICE) and UFS crypto as a temporary workaround. Disabled: - CONFIG_QCOM_INLINE_CRYPTO_ENGINE - CONFIG_SCSI_UFS_CRYPTO Will be reverted once ICE probe is fixed. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a5cd0552d921b..3e70e46afed10 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -78,3 +78,6 @@ CONFIG_NET_NS=y CONFIG_PID_NS=y CONFIG_UTS_NS=y +# Disable ICE/UFS crypto +# CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set +# CONFIG_SCSI_UFS_CRYPTO is not set From 9527f338fa3acf1fa73c8f4853727b468cfdb6fe Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Wed, 24 Dec 2025 18:34:18 +0530 Subject: [PATCH 0301/1058] QCLINUX: defconfig: enable Remoteproc cooling feature Enable Remoteproc cooling feature config. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3e70e46afed10..deb196ca4eced 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -42,6 +42,8 @@ CONFIG_PM_WAKELOCKS_LIMIT=0 CONFIG_PM=y CONFIG_POWERCAP=y CONFIG_QCA808X_PHY=m +CONFIG_QCOM_QMI_COOLING=y +CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From dd4addd961ea865571f669190ccb17944566518a Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Thu, 8 Jan 2026 14:14:29 +0530 Subject: [PATCH 0302/1058] QCLINUX: arm64: configs: qcom.config: Enable CONNECTOR, PROC_EVENTS Enable CONFIG_CONNECTOR and CONFIG_PROC_EVENTS to allow userspace to receive process lifecycle events (fork/exec/exit) via the proc connector over netlink. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index deb196ca4eced..8a86a3cb7813f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -11,6 +11,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CONNECTOR=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m @@ -41,6 +42,7 @@ CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set CONFIG_PM=y CONFIG_POWERCAP=y +CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y CONFIG_REMOTEPROC_THERMAL=y From 2fbb5d0b78910f283ff708ac8e041162ae9683d8 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Mon, 5 Jan 2026 15:59:47 +0800 Subject: [PATCH 0303/1058] QCLINUX: qcom.config: add crypto corresponding config Enable crypto api for user test. The configs are for testapp that's why the kernel upstream team would suggest having this enabled for clients who needs it and not by default since in qcom we need this, we should be enabling ideally in qcom-next. Signed-off-by: Wenjia Zhang --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 8a86a3cb7813f..bdb40e6edf745 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -85,3 +85,9 @@ CONFIG_UTS_NS=y # Disable ICE/UFS crypto # CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set # CONFIG_SCSI_UFS_CRYPTO is not set + +# Support Crypto api +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_AEAD=y From bdde71da3ea46657f7e80cb1b7b1ea60650c5e20 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 19 Jan 2026 15:47:00 +0800 Subject: [PATCH 0304/1058] QCLINUX: prune.config: Enable backlight config for Hamoa/Purwa Hamoa/Purwa currently requires the backlight node from the eDP device, but this macro was overridden by CONFIG_DRM_NOUVEAU. Remove it from prune.config to properly enable the BACKLIGHT_* related config. Signed-off-by: Yongxing Mou --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index 9fc201d4eb924..a0a54f95fcd1a 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -224,7 +224,6 @@ # CONFIG_DRM_I2C_NXP_TDA998X is not set # CONFIG_DRM_MALI_DISPLAY is not set # CONFIG_DRM_KOMEDA is not set -# CONFIG_DRM_NOUVEAU is not set # CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set # CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set # CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set From 7d276bbd6e3794245b5622f71fb37c05f82c285c Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 23 Jan 2026 13:32:49 +0530 Subject: [PATCH 0305/1058] QCLINUX: qcom.config: Enable 39-bit VA space for 4K-page builds For Qualcomm 4K-page based builds, explicitly enable VA_BITS_39 in the qcom.config fragment. Lower-end arm64 systems typically do not benefit from a 48/52-bit VA space, while they do benefit from smaller page tables and reduced TLB pressure. Selecting 39-bit VA sizing aligns better with constraints and performance characteristics of lower-end Qualcomm platforms. This change does not affect 64K-page builds (which retain 48/52-bit VA). Background: - With 4K pages, arm64 supports 39-bit (3-level) or 48-bit (4-level) VAs. - 52-bit VAs are only available with 64K pages and ARMv8.2-LVA, and kernels must be able to fall back to 48-bit at boot. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index bdb40e6edf745..583c51acfeda2 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,6 +4,7 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ARM64_VA_BITS_39=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y From c74f7320891f29e08da2ca10cddbbbcf7504a448 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Tue, 27 Jan 2026 15:59:30 +0800 Subject: [PATCH 0306/1058] QCLINUX: qcom.config: enable the ICE related config Below is the reason why config aren't enable in upstream: Not all filesystem support encryption, the default config must be safe for all situation. Upstream kernel keeps optional features off by default. Filesystem encryption must be enabled in per-filesystem. Kernel developmenters added options to dosable fscrypt per-filesystem means it's not intended as default. CRs-Fixed: 4418940 Signed-off-by: Wenjia Zhang --- arch/arm64/configs/qcom.config | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 583c51acfeda2..95ffbc244bbe1 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -83,12 +83,15 @@ CONFIG_NET_NS=y CONFIG_PID_NS=y CONFIG_UTS_NS=y -# Disable ICE/UFS crypto -# CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set -# CONFIG_SCSI_UFS_CRYPTO is not set - # Support Crypto api CONFIG_CRYPTO_USER_API=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_USER_API_AEAD=y + +# Support ICE/UFS crypto driver +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_FS_ENCRYPTION=y From e3ce98d173c4e8427838aa629afe51d26509b8b9 Mon Sep 17 00:00:00 2001 From: Gopi Botlagunta Date: Wed, 12 Nov 2025 20:18:12 +0530 Subject: [PATCH 0307/1058] FROMLIST: arm64: configs: Update defconfig for DSI-LVDS bridge support Enable the LT9211 bridge driver to support DSI-to-LVDS conversion on the Qualcomm RB3GEN2 Industrial Kit. Signed-off-by: Gopi Botlagunta Co-developed-by: Yi Zhang Signed-off-by: Yi Zhang Link: https://lore.kernel.org/lkml/20260130-add-lt9211c-bridge-for-rb3gen2-industrial-mezzanine-v2-2-a98714fa1531@oss.qualcomm.com/ --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 919553fbf5f48..de7a06dcf06e9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -961,6 +961,7 @@ CONFIG_DRM_FSL_LDB=m CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m +CONFIG_DRM_LONTIUM_LT9211=m CONFIG_DRM_LONTIUM_LT9611=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m From 828b7c17a1c8da1a92c02b298a0faf99ec44ba1d Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 29 Jan 2026 15:52:47 +0530 Subject: [PATCH 0308/1058] QCLINUX: qcom.config: Enable FTRACE option for performance profiling Enable kernel tracing option in qcom.config to support performance profiling on Qualcomm arm64 builds. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 95ffbc244bbe1..0c519f4f5699b 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -95,3 +95,6 @@ CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_SCSI_UFS_CRYPTO=y CONFIG_FS_ENCRYPTION=y + +# Support performance profiling +CONFIG_FTRACE=y From 904d3f688290050f22496158f809b46343ef23e1 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Wed, 28 Jan 2026 00:56:39 +0530 Subject: [PATCH 0309/1058] FROMLIST: arm64: defconfig: Enable VIDEOCC and CAMCC drivers on Qualcomm X1P42100 Enable video and camera clock controller drivers for their respective functionalities on Qualcomm X1P42100-CRD and similar other platforms with Snapdragon X1P42100 SoC. Signed-off-by: Jagadeesh Kona Link: https://lore.kernel.org/r/20260128-purwa-videocc-camcc-v1-8-b23de57df5ba@oss.qualcomm.com Signed-off-by: Taniya Das --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index de7a06dcf06e9..08f49bc162e78 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1479,7 +1479,9 @@ CONFIG_CLK_X1E80100_DISPCC=m CONFIG_CLK_X1E80100_GCC=y CONFIG_CLK_X1E80100_GPUCC=m CONFIG_CLK_X1E80100_TCSRCC=y +CONFIG_CLK_X1P42100_CAMCC=m CONFIG_CLK_X1P42100_GPUCC=m +CONFIG_CLK_X1P42100_VIDEOCC=m CONFIG_CLK_QCM2290_GPUCC=m CONFIG_QCOM_A53PLL=y CONFIG_QCOM_CLK_APCS_MSM8916=y From 6e44f05a8162318bab8cedee727d8b140ec319a5 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 18 Feb 2026 12:00:01 +0530 Subject: [PATCH 0310/1058] Revert "QCLINUX: qcom.config: Enable 39-bit VA space for 4K-page builds" This reverts commit 02fdded1047f4a65082e9ee523dec4af032d99bc. Since bootup issues are observed after enabling 39-bit VA, reverting it untill issues are root caused and fixed. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0c519f4f5699b..8dc73c1b87af0 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,7 +4,6 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y -CONFIG_ARM64_VA_BITS_39=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y From a813a3d48db793e3d0a6ea13268628624680e0e2 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 20 Feb 2026 08:33:37 +0530 Subject: [PATCH 0311/1058] QCLINUX: qcom.config: Enable CPUidle Teo and Menu governors Menu governor gets default enabled if Teo governor is not compiled in. Menu still stays as default governor when both are compiled in due to menu having higher rating than teo. Keeping Teo available helps in evaluating power and performance without spinning builds. Enable both menu and teo governors for CPUidle. Signed-off-by: Maulik Shah --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 8dc73c1b87af0..327fc43332c58 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -19,6 +19,8 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y # CONFIG_DEBUG_INFO_REDUCED is not set CONFIG_DMABUF_HEAPS=y From ca034bffcc80a2aadd63f22e565dc7de53e4265b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 20 Feb 2026 15:46:58 +0530 Subject: [PATCH 0312/1058] FROMLIST: arm64: defconfig: Enable Glymur clock controllers Enable the Glymur video and gpu clock controller for their respective functionalities on the Qualcomm Glymur CRD boards. Link: https://lore.kernel.org/r/20260220-glymur_mmcc_dt_config-v1-2-e0e2f43a32af@oss.qualcomm.com Signed-off-by: Taniya Das Reviewed-by: Dmitry Baryshkov --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 08f49bc162e78..bee36112622da 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1467,7 +1467,9 @@ CONFIG_CLK_ELIZA_GCC=y CONFIG_CLK_ELIZA_TCSRCC=m CONFIG_CLK_GLYMUR_DISPCC=m CONFIG_CLK_GLYMUR_GCC=y +CONFIG_CLK_GLYMUR_GPUCC=m CONFIG_CLK_GLYMUR_TCSRCC=m +CONFIG_CLK_GLYMUR_VIDEOCC=m CONFIG_CLK_KAANAPALI_CAMCC=m CONFIG_CLK_KAANAPALI_DISPCC=m CONFIG_CLK_KAANAPALI_GCC=y From 70645bae9b3a0fec76e0c9f657c24e47311b18f2 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 2 Mar 2026 18:33:59 +0530 Subject: [PATCH 0313/1058] QCLINUX: qcom.config: enable CONFIG_CMA for qcom chipsets CMA imposes system-wide memory constraints by reserving boot-time memory and restricting it to movable allocations. This alters allocator behavior even when CMA is not explicitly used. Since CMA sizing and applicability are platform-specific, mm/Kconfig intentionally provides no default opt-in for CONFIG_CMA. Enable CONFIG_CMA for all qcom chipsets Signed-off-by: Bibek Kumar Patro bibek.patro@oss.qualcomm.com --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 327fc43332c58..78478aef4e388 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -11,6 +11,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CMA=y CONFIG_CONNECTOR=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m From 2549688c33c5226b3b52d6aa560c4b665f714e47 Mon Sep 17 00:00:00 2001 From: Dipa Mantre Date: Mon, 23 Mar 2026 21:06:50 +0530 Subject: [PATCH 0314/1058] QCLINUX: defconfig: Enable Qualcomm BCL driver Enable Qualcomm BCL driver config. Signed-off-by: Dipa Mantre --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 78478aef4e388..c48eb016accbd 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -58,6 +58,7 @@ CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y CONFIG_SENSORS_EMC2305=y +CONFIG_SENSORS_QCOM_BCL=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 69b37bdea05e1daec2af7e1641b6c4006aed6943 Mon Sep 17 00:00:00 2001 From: gaolez Date: Wed, 18 Mar 2026 16:15:38 +0800 Subject: [PATCH 0315/1058] QCLINUX: qcom.config: Enable testmode config Enabling this option exposes the NL80211_CMD_TESTMODE command, which permits userspace applications to send vendor-specific test commands to the driver for diagnostics and validation purposes. Signed-off-by: gaolez --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index c48eb016accbd..37d8aea51bed7 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -37,6 +37,7 @@ CONFIG_INPUT_UINPUT=y CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y +CONFIG_NL80211_TESTMODE=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_PM_AUTOSLEEP=y From bc877dc753ed6f0c9c308f2d3ee495077cf16bfb Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 24 Mar 2026 15:36:35 +0800 Subject: [PATCH 0316/1058] QCLINUX: qcom.config: update TGU config The TGU config has been changed in latest TGU driver version. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 37d8aea51bed7..8a4eafaec9db0 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -18,7 +18,6 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m -CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_TPDM=m CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_GOV_TEO=y @@ -49,6 +48,7 @@ CONFIG_POWERCAP=y CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y +CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y From 3027bb1a2fdd2a421f2a8ab8894a1ce8b07d5841 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 25 Mar 2026 15:23:24 +0800 Subject: [PATCH 0317/1058] QCLINUX: qcom.config: fix the TNOC config Fix the wrong config for CORESIGHT_TNOC. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 8a4eafaec9db0..a46bdd16e84aa 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -13,7 +13,7 @@ CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CMA=y CONFIG_CONNECTOR=y -CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m From f3d5656a742a422a463ce3b39f4c8730f5932405 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Sat, 28 Mar 2026 16:49:50 +0530 Subject: [PATCH 0318/1058] QCLINUX: qcom.config: Enable compressed firmware support Enable support for loading of compressed firmware. With compressed firmware binaries kernel is not able to load the firmware. Enable kernel configs to support compressed firmware. Signed-off-by: Salendarsingh Gaud --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a46bdd16e84aa..334af2a92b903 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,8 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_FW_LOADER_COMPRESS_ZSTD=y CONFIG_GUNYAH_WATCHDOG=y CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y From cc7eacabbaba2c6f69a13479c750d174bafc344c Mon Sep 17 00:00:00 2001 From: Qian Zhang Date: Tue, 17 Mar 2026 17:20:25 +0800 Subject: [PATCH 0319/1058] QCLINUX: debug: Enable ATH11K CFR Enable RELAY and ATH11K_CFR for channel Frequency Response (CFR) module. Signed-off-by: Qian Zhang --- kernel/configs/debug.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 6a9237a66deb7..8d45cf4500bfb 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -120,6 +120,7 @@ CONFIG_PREEMPT=y # # Qualcomm Debug Configs # +CONFIG_ATH11K_CFR=y CONFIG_ATH11K_COREDUMP=y CONFIG_ATH11K_DEBUG=y CONFIG_ATH11K_DEBUGFS=y @@ -146,6 +147,7 @@ CONFIG_PREEMPTIRQ_TRACEPOINTS=y CONFIG_PM_ADVANCED_DEBUG=y CONFIG_PM_DEBUG=y CONFIG_PM_SLEEP_DEBUG=y +CONFIG_RELAY=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y CONFIG_TRACEPOINTS=y From 6b4425db18a1ebfaefa747985fcf7472a4b53e0d Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 24 Mar 2026 12:18:21 +0530 Subject: [PATCH 0320/1058] QCLINUX: qcom.config: Enable MMC_CRYPTO for ICE emmc To enable ICE, require MMC_CRYPTO for sdhci and SCSI_UFS_CRYPTO for ufs based targets. SCSI_UFS_CRYPTO is already present, add MMC_CRYPTO for enabling inline encryption. Signed-off-by: Kuldeep Singh --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 334af2a92b903..ff28a044e60b9 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -100,6 +100,7 @@ CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_MMC_CRYPTO=y CONFIG_FS_ENCRYPTION=y # Support performance profiling From 391eaf1dacd739742cc6d59e334c535106778655 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 15 Apr 2026 10:08:10 +0530 Subject: [PATCH 0321/1058] QCLINUX: prune.config: Enable Realtek PHY config for Rb3Gen2 Industrial board The Rb3Gen2 Industrial board has the Realtek RTL8221 PHY which fails to function correctly without the Realtek PHY driver. Remove CONFIG_REALTEK_PHY from prune.config to properly enable it. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index a0a54f95fcd1a..c962fd6fb4e18 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -100,7 +100,6 @@ # CONFIG_MARVELL_PHY is not set # CONFIG_MARVELL_10G_PHY is not set # CONFIG_MICROSEMI_PHY is not set -# CONFIG_REALTEK_PHY is not set # CONFIG_ROCKCHIP_PHY is not set # CONFIG_DP83867_PHY is not set # CONFIG_DP83TD510_PHY is not set From 7286c40a0d50f920daa48b3b24ecb092e98545e2 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 17 Apr 2026 11:17:28 +0530 Subject: [PATCH 0322/1058] QCLINUX: qcom.config: Enable SYSFS config Enable CONFIG_WATCHDOG_SYSFS=y in arch/arm64/configs/qcom.config. Without this option, watchdog core does not expose sysfs watchdog attributes (e.g. timeout, timeleft, status, bootstatus, etc.) under /sys/class/watchdog/watchdogN/, which matches the observed behavior on iq-9075-evk where only basic entries were present. This makes watchdog sysfs nodes available on qcom-next/6.18.y builds that use this config fragment. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index ff28a044e60b9..e1c1edf740c88 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -78,6 +78,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_SYSFS=y CONFIG_ZRAM=y # Kubernetes support From 6b0608023c61e88e905609f9aa72b20632cf5f82 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 23 Apr 2026 12:38:59 +0530 Subject: [PATCH 0323/1058] QCLINUX: prune.config: Disable MMU_500 CPRE ERRATA workaround for Qualcomm SOC Disable MMU-500's CPRE ERRATA workaround for Qualcomm SOCs, to not disable prefetch functionality by CPRE bit reset in arm_mmu500_reset path during system suspend-resume cycle. Signed-off-by: Bibek Kumar Patro --- arch/arm64/configs/prune.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index c962fd6fb4e18..e930a30663423 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -398,3 +398,4 @@ # CONFIG_SUN_PARTITION is not set # CONFIG_SYSV68_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set +# CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA is not set From 3f09f8a52799142eb93bddc23c0347798ddbc108 Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Thu, 7 May 2026 00:34:27 +0530 Subject: [PATCH 0324/1058] FROMLIST: arm64: defconfig: Enable Qualcomm reference device EC driver Enable EC_QCOM_HAMOA as a module to support the embedded controller found on Qualcomm CRD reference devices such as Hamoa and Glymur. Link: https://lore.kernel.org/lkml/20260511-add-driver-for-ec-v9-6-e5437c39b7f8@oss.qualcomm.com/ Reviewed-by: Pankaj Patil Signed-off-by: Anvesh Jain P --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index bee36112622da..0a79fd987efbf 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1428,6 +1428,7 @@ CONFIG_EC_HUAWEI_GAOKUN=m CONFIG_EC_LENOVO_YOGA_C630=m CONFIG_EC_LENOVO_THINKPAD_T14S=m CONFIG_COMMON_CLK_APPLE_NCO=m +CONFIG_EC_QCOM_HAMOA=m CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y CONFIG_COMMON_CLK_SCPI=y From 1c352f4c9718bf9594f290fea15b6555bb04d21b Mon Sep 17 00:00:00 2001 From: Pragnesh Papaniya Date: Tue, 12 May 2026 14:08:03 +0530 Subject: [PATCH 0325/1058] QCLINUX: qcom.config: Enable QCOM SCMI memlat bus scaling Enable the QCOM SCMI Generic Vendor Extension protocol (=y), the remote devfreq governor (=y), and the QCOM SCMI memlat devfreq device driver (=m) for LLCC/DDR/DDR_QOS bus scaling on Glymur and Hamoa SoCs. SCMI_QCOM_MEMLAT_DEVFREQ follows QCOM_CPUCP_MBOX at =m since it depends on that mailbox transport. Link: https://lore.kernel.org/lkml/20260507062237.78051-1-sibi.sankar@oss.qualcomm.com/ Signed-off-by: Sibi Sankar --- arch/arm64/configs/qcom.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index e1c1edf740c88..e7a86c325ac93 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -106,3 +106,8 @@ CONFIG_FS_ENCRYPTION=y # Support performance profiling CONFIG_FTRACE=y + +# QCOM SCMI memlat bus scaling +CONFIG_QCOM_SCMI_GENERIC_EXT=y +CONFIG_DEVFREQ_GOV_REMOTE=y +CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m From 9bf83c16b90b2b6ec8cc53067c60eb1a1140ff7b Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Mon, 11 May 2026 16:08:57 +0530 Subject: [PATCH 0326/1058] FROMLIST: arm64: defconfig: Enable CAMCC driver on Qualcomm Glymur SoC Enable camera clock controller driver for camera functionality on Qualcomm Glymur-CRD and similar other platforms with Glymur SoC. Link: https://lore.kernel.org/r/20260429-glymur_camcc-v2-4-0c3fd1977869@oss.qualcomm.com Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jagadeesh Kona Signed-off-by: Taniya Das --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0a79fd987efbf..173af1ed59f06 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1466,6 +1466,7 @@ CONFIG_COMMON_CLK_QCOM=y CONFIG_CLK_ELIZA_DISPCC=m CONFIG_CLK_ELIZA_GCC=y CONFIG_CLK_ELIZA_TCSRCC=m +CONFIG_CLK_GLYMUR_CAMCC=m CONFIG_CLK_GLYMUR_DISPCC=m CONFIG_CLK_GLYMUR_GCC=y CONFIG_CLK_GLYMUR_GPUCC=m From ded3ae333d74d0ecf9dc6229a24c4fcf00b83109 Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Tue, 19 May 2026 19:17:34 +0530 Subject: [PATCH 0327/1058] QCLINUX: defconfig: Enable Qualcomm SPEL driver The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various power domains including System, SoC, CPU clusters, GPU, and various other subsystems. The driver integrates with the Linux powercap framework, exposing SPEL capabilities through powercap sysfs interfaces. This allows userspace applications and thermal management daemons to monitor energy consumption and configure power limits for optimal power/performance balance. Signed-off-by: Aastha Pandey --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index e7a86c325ac93..f1d97332f9099 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -50,6 +50,7 @@ CONFIG_POWERCAP=y CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y +CONFIG_QCOM_SPEL=m CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y From 6f32352271a194f60a88087528015c41f40f4d4d Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Tue, 28 Apr 2026 15:20:41 +0530 Subject: [PATCH 0328/1058] QCLINUX: arm64: configs: Add Linux software RAID support Enable Linux software RAID support using MD framework. Signed-off-by: Monish Chunara Signed-off-by: Shubham Chouhan --- arch/arm64/configs/defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 173af1ed59f06..a436769178c78 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -339,6 +339,10 @@ CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y CONFIG_BLK_DEV_DM=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m From ca52b4c519829a71d89aa24349300be9e0a211ed Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 15 Apr 2026 15:23:54 +0530 Subject: [PATCH 0329/1058] QCLINUX: arm64: configs: Enable SmartPQI support Enable SmartPQI support in arm64 configs to provide HW RAID support for systems using SmartPQI-based RAID controllers. Signed-off-by: Monish Chunara Signed-off-by: Sayali Lokhande --- arch/arm64/configs/qcom.config | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f1d97332f9099..4fbe2861e4e04 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -105,6 +105,18 @@ CONFIG_SCSI_UFS_CRYPTO=y CONFIG_MMC_CRYPTO=y CONFIG_FS_ENCRYPTION=y +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=m +CONFIG_BLK_DEV_BSG=y +# +# SCSI Transports +# +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_SMARTPQI=m + # Support performance profiling CONFIG_FTRACE=y From 3fdb6fa5eccffb8e3d98b641c16ddd58583ffbe4 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Fri, 29 May 2026 15:12:22 +0530 Subject: [PATCH 0330/1058] QCLINUX: arm64: configs: enable USB configfs UVC and UAC2 functions Enable USB configfs support for UVC (USB Video Class) and UAC2 (USB Audio Class 2) function drivers in the Qualcomm ARM64 defconfig. This allows the platform to expose video and audio gadget functions via configfs, enabling use cases such as USB camera and audio device emulation over gadget mode. These options are required for test and development scenarios involving multimedia streaming over USB. Signed-off-by: Pratham Pratap --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 4fbe2861e4e04..bafa87f254ab9 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -67,6 +67,8 @@ CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_VCPU_STALL_DETECTOR=y CONFIG_VHOST_NET=y CONFIG_VHOST_VSOCK=y From 7e336a5263c1113538bbc2b31026019f44b21db1 Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Wed, 3 Jun 2026 18:21:38 +0530 Subject: [PATCH 0331/1058] QCLINUX: arm64: configs: qcom.config: Enable CONFIG_SWIOTLB_DYNAMIC Enable CONFIG_SWIOTLB_DYNAMIC to reduce static SWIOTLB memory reservation by allowing the bounce buffer pool to grow dynamically based on runtime DMA requirements. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index bafa87f254ab9..06d7a8239eb95 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -63,6 +63,7 @@ CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y CONFIG_SENSORS_EMC2305=y CONFIG_SENSORS_QCOM_BCL=y +CONFIG_SWIOTLB_DYNAMIC=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From c74bd2349f2013aca08224a3b5b0da44cdb7dde6 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Mon, 11 May 2026 13:58:26 +0530 Subject: [PATCH 0332/1058] QCLINUX: arm64: configs: Enable GPU virtualization Enable DRM VirtIO GPU configs to support GPU virtualization Signed-off-by: Shivam Rawat --- arch/arm64/configs/qcom.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 06d7a8239eb95..798f145cde327 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -127,3 +127,7 @@ CONFIG_FTRACE=y CONFIG_QCOM_SCMI_GENERIC_EXT=y CONFIG_DEVFREQ_GOV_REMOTE=y CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m + +# GPU Virtualization support +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_VIRTIO_GPU_KMS=m From 76e62fd4716ad1a2c7b7f24f2eeb33987ebfc67c Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Tue, 9 Jun 2026 21:17:00 +0530 Subject: [PATCH 0333/1058] QCLINUX: arm64: configs: qcom.config: Enable LZ4 backend for zram Enable CONFIG_ZRAM_BACKEND_LZ4 to allow use of LZ4 compression for zram. LZ4 offers low latency and reduced CPU overhead, making it well-suited for embedded systems. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 798f145cde327..a4a00c23b56a3 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -84,6 +84,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_WATCHDOG_SYSFS=y CONFIG_ZRAM=y +CONFIG_ZRAM_BACKEND_LZ4=y # Kubernetes support CONFIG_CFS_BANDWIDTH=y From 10007fd819f0debe8c726780b94d3b07ac03cf4e Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 11 Jun 2026 11:18:55 +0530 Subject: [PATCH 0334/1058] QCLINUX: arm64: configs: qcom: Set DRIVER_DEFERRED_PROBE_TIMEOUT to 60 Set the deferred probe timeout to 60 seconds in the Qualcomm config fragment.With the kernel default of 10s ,we are observing probe deferrals on Qualcomm platforms where supplier drivers (e.g. regulators, clocks) are probing late; 60s gives sufficient margin without waiting indefinitely. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a4a00c23b56a3..041109f489a17 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=60 CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_FW_LOADER_COMPRESS=y From c696ffc4c35fa6d7c55f2638e942c7b4aa25c2d3 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 11 Jun 2026 16:10:45 +0530 Subject: [PATCH 0335/1058] QCLINUX: kernel: debug.config: Additional debug configs Add configs for ATH11K/ATH12K debug/coredump/tracing, CMA debug, pstore/EFI vars, ftrace extensions (dynamic ftrace with args/call-ops/ direct-calls, hwlat/timerlat/sched tracers, snapshot), lockup detectors, lock debugging (spinlock, rwsems, list), DMABUF sysfs stats, WQ watchdog, PM debug, and various other debug instrumentation. These configs are already part of QLI.1.0. Adding them to QLI.2.0 and QLI mainline. Signed-off-by: Anurag Pateriya --- kernel/configs/debug.config | 48 ++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 8d45cf4500bfb..f6ca58cf61e04 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -125,31 +125,73 @@ CONFIG_ATH11K_COREDUMP=y CONFIG_ATH11K_DEBUG=y CONFIG_ATH11K_DEBUGFS=y CONFIG_ATH11K_TRACING=y +CONFIG_ATH12K_COREDUMP=y CONFIG_ATH12K_DEBUG=y CONFIG_ATH12K_DEBUGFS=y CONFIG_ATH12K_TRACING=y -CONFIG_ATH12K_COREDUMP=y CONFIG_CFG80211_DEBUGFS=y CONFIG_CMA_DEBUG=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000 CONFIG_DEBUG_LIST=y CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_EFI_VARS_PSTORE=y +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y CONFIG_FTRACE_SYSCALLS=y +CONFIG_FUNCTION_ALIGNMENT=8 +CONFIG_FUNCTION_ALIGNMENT_8B=y CONFIG_FUNCTION_GRAPH_TRACER=y # CONFIG_FW_LOADER_DEBUG is not set +CONFIG_GENERIC_TRACER=y CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_HWLAT_TRACER=y CONFIG_IRQSOFF_TRACER=y CONFIG_KPROBE_EVENTS=y +CONFIG_LOCALVERSION="" +CONFIG_LOCKUP_DETECTOR=y CONFIG_MAC80211_DEBUGFS=y CONFIG_NL80211_TESTMODE=y -CONFIG_PREEMPT_TRACER=y -CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y +CONFIG_PCIEAER_INJECT=y +CONFIG_PID_IN_CONTEXTIDR=y CONFIG_PM_ADVANCED_DEBUG=y CONFIG_PM_DEBUG=y CONFIG_PM_SLEEP_DEBUG=y +CONFIG_PREEMPT_TRACER=y +CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_BLK=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_PMSG=y +CONFIG_RCU_CPU_STALL_CPUTIME=y +CONFIG_REED_SOLOMON=y CONFIG_RELAY=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y +CONFIG_TEST_DYNAMIC_DEBUG=y +CONFIG_TIMERLAT_TRACER=y +CONFIG_TRACE_IRQFLAGS=y +CONFIG_TRACE_IRQFLAGS_NMI=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y CONFIG_TRACEPOINTS=y CONFIG_TRACING=y CONFIG_UPROBE_EVENTS=y +CONFIG_WQ_CPU_INTENSIVE_REPORT=y +CONFIG_WQ_WATCHDOG=y From 602d96baa80cb48aaa3326bb6623a2dcd1f306a6 Mon Sep 17 00:00:00 2001 From: Hariprasad kelam Date: Wed, 17 Jun 2026 14:15:45 +0530 Subject: [PATCH 0336/1058] QCLINUX: qcom.config: Enable Intel IXGBE driver Enable the IXGBE and IXGBEVF drivers to support the Intel X550 T2 NIC on QLI boards with SR-IOV support. Signed-off-by: Hariprasad kelam --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 041109f489a17..903928f2be129 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -36,6 +36,8 @@ CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_INPUT_UINPUT=y +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y From cf973608cd223b305b1ed5ff2af710cc0faa947e Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 23 Jun 2026 16:12:26 +0530 Subject: [PATCH 0337/1058] QCLINUX: prune.config: Enable the TI DP83867 PHY driver The Shikra EVK boards have an RGMII TI PHY connected to the dual EMACs of the SoC. Remove its config from prune.config to enable its driver. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index e930a30663423..40665245e406f 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -101,7 +101,6 @@ # CONFIG_MARVELL_10G_PHY is not set # CONFIG_MICROSEMI_PHY is not set # CONFIG_ROCKCHIP_PHY is not set -# CONFIG_DP83867_PHY is not set # CONFIG_DP83TD510_PHY is not set # CONFIG_VITESSE_PHY is not set # CONFIG_CAN_FLEXCAN is not set From 62b81220d7508386e1af514a2a347f0ad367574f Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sat, 13 Jun 2026 18:21:35 +0530 Subject: [PATCH 0338/1058] QCLINUX: arm64: configs: qcom: Enable SCHED_CLASS_EXT (sched_ext) Enable the extensible scheduling class (SCX) which allows BPF-based scheduling policies. Also enable its cgroup dependencies: - CONFIG_SCHED_CLASS_EXT=y -- core sched_ext class BTF support (DEBUG_INFO_BTF, DEBUG_INFO_BTF_MODULES) is enabled which is required by SCHED_CLASS_EXT and also needed for BPF CO-RE and kernel module BTF. Signed-off-by: Ashay Jaiswal --- arch/arm64/configs/qcom.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 903928f2be129..3ca39599c6332 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -23,6 +23,9 @@ CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y # CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_INFO_BTF=y +CONFIG_DEBUG_INFO_BTF_MODULES=y +# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y @@ -56,6 +59,7 @@ CONFIG_QCOM_QMI_COOLING=y CONFIG_QCOM_SPEL=m CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y +CONFIG_SCHED_CLASS_EXT=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From 5bb4e31081b98e514a031b7dd86af7ec08ed8057 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 17 Mar 2026 22:44:28 +0530 Subject: [PATCH 0339/1058] FROMLIST: arm64: defconfig: Enable clock controllers on Qualcomm Eliza SoC Enable the video, camera and gpu clock controllers for their respective functionalities on the Qualcomm Eliza boards. Link: https://lore.kernel.org/r/20260317-eliza_mm_clock_controllers_v1-v1-7-4696eeda8cfb@oss.qualcomm.com Signed-off-by: Taniya Das --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a436769178c78..7893be69c9e02 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1467,9 +1467,12 @@ CONFIG_COMMON_CLK_MT8192_SCP_ADSP=y CONFIG_COMMON_CLK_MT8192_VDECSYS=y CONFIG_COMMON_CLK_MT8192_VENCSYS=y CONFIG_COMMON_CLK_QCOM=y +CONFIG_CLK_ELIZA_CAMCC=m CONFIG_CLK_ELIZA_DISPCC=m CONFIG_CLK_ELIZA_GCC=y +CONFIG_CLK_ELIZA_GPUCC=m CONFIG_CLK_ELIZA_TCSRCC=m +CONFIG_CLK_ELIZA_VIDEOCC=m CONFIG_CLK_GLYMUR_CAMCC=m CONFIG_CLK_GLYMUR_DISPCC=m CONFIG_CLK_GLYMUR_GCC=y From 1a8cf1ce596fce7858b3a0f717c1151d1891a76b Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Sun, 9 Nov 2025 20:07:21 +0530 Subject: [PATCH 0340/1058] FROMLIST: arm64: dts: qcom: qcm6490-idp: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets in qcm6490-idp as reboot-modes. Describe the resets: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-8-46e085bca4cc@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 +- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..28b09b5ff4a65 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -863,7 +863,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index bdc02260f902b..76a7d3fef1a91 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -786,6 +786,13 @@ bias-disable; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_id_0 { status = "okay"; }; From 8a81987316fc309e10fb2f5718d7cb06d94a2d1a Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Sun, 9 Nov 2025 20:07:22 +0530 Subject: [PATCH 0341/1058] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets in qcs6490-rb3gen2 as reboot-modes. Describe the resets: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-9-46e085bca4cc@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..decc964d2d98b 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -1105,6 +1105,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qup_uart7_cts { /* * Configure a bias-bus-hold on CTS to lower power From 2f8abb9a606bd9d9194983ee7ed3d0a4ee20bca2 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Wed, 1 Jul 2026 18:03:24 +0530 Subject: [PATCH 0342/1058] QCLINUX: qcom.config: Enable DMA_CMA for DMA-BUF heap support Enable CONFIG_DMA_CMA as a dependency to allow the DMA-BUF heap configs (DMABUF_HEAPS, DMABUF_HEAPS_CMA, DMABUF_HEAPS_SYSTEM) to be selected in qcom.config. Signed-off-by: Bibek Kumar Patro --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3ca39599c6332..b286309f0c251 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_BTF_MODULES=y # CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set +CONFIG_DMA_CMA=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y From 6148ef651ae22af7c975998dcec093794e466be0 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 28 Nov 2025 16:02:40 +0530 Subject: [PATCH 0343/1058] FROMLIST: remoteproc: qcom: Fix NULL pointer issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a scenario, when fatal interrupt triggers rproc crash handling while a user-space recovery is initiated in parallel. The overlapping recovery/stop sequences race on rproc state and subdevice teardown, resulting in a NULL pointer dereference in the GLINK SMEM unregister path. Process-A Process-B fatal error interrupt happens rproc_crash_handler_work() mutex_lock_interruptible(&rproc->lock); ... rproc->state = RPROC_CRASHED; ... mutex_unlock(&rproc->lock); rproc_trigger_recovery() mutex_lock_interruptible(&rproc->lock); qcom_pas_stop() qcom_q6v5_pas 20c00000.remoteproc: failed to shutdown: -22 remoteproc remoteproc3: can't stop rproc: -22 mutex_unlock(&rproc->lock); echo enabled > /sys/class/remoteproc/remoteprocX/recovery recovery_store() rproc_trigger_recovery() mutex_lock_interruptible(&rproc->lock); rproc_stop() glink_subdev_stop() qcom_glink_smem_unregister() ==| | V Unable to handle kernel NULL pointer dereference at virtual address 0000000000000358 It is tempting to introduce a remoteproc state that could be set from the ->ops->stop() callback, which would have avoided the second attempt and prevented the crash. However, making remoteproc recovery dependent on manual intervention or a system reboot is not ideal. We should always try to recover the remote processor if possible. A failure in the ->ops->stop() callback might be temporary or caused by a timeout, and a recovery attempt could still succeed, as seen in similar scenarios. Therefore, instead of adding a restrictive state, let’s add a NULL check at the appropriate places to avoid a kernel crash and allow the system to move forward gracefully. Link: https://lore.kernel.org/r/20251128103240.1723386-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Mukesh Ojha Reviewed-by: Bryan O'Donoghue --- drivers/remoteproc/qcom_common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index e1a955476c9b3..1f406bfcb1f59 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -226,6 +226,9 @@ static void glink_subdev_stop(struct rproc_subdev *subdev, bool crashed) { struct qcom_rproc_glink *glink = to_glink_subdev(subdev); + if (!glink->edge) + return; + qcom_glink_smem_unregister(glink->edge); glink->edge = NULL; } @@ -337,6 +340,9 @@ static void smd_subdev_stop(struct rproc_subdev *subdev, bool crashed) { struct qcom_rproc_subdev *smd = to_smd_subdev(subdev); + if (!smd->edge) + return; + qcom_smd_unregister_edge(smd->edge); smd->edge = NULL; } From 98e66a0caa45d5eb4ffaed2cb1512ffac307a8db Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:39 +0530 Subject: [PATCH 0344/1058] FROMLIST: dt-bindings: i2c: qcom,i2c-geni: Document multi-owner controller support Document a DeviceTree property to describe QUP-based I2C controllers that are shared with one or more other system processors. On some Qualcomm platforms, a QUP-based I2C controller may be accessed by multiple system processors (for example, APPS and DSP). In such configurations, the operating system must not assume exclusive ownership of the controller or its associated hardware resources. The new qcom,qup-multi-owner property indicates that the controller is externally shared and that the operating system must avoid operations which rely on sole control of the hardware. Link: https://lore.kernel.org/all/20260331114742.2896317-2-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- .../devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml index 51534953a69cf..9401dc2d50522 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml @@ -60,6 +60,13 @@ properties: power-domains: maxItems: 1 + qcom,qup-multi-owner: + type: boolean + description: + Indicates that the QUP-based controller is shared with one or more + other system processors and must not be assumed to have exclusive + ownership by the operating system. + reg: maxItems: 1 From 39e6c15430143f014d0198b1c99fcd841d5646ce Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:40 +0530 Subject: [PATCH 0345/1058] FROMLIST: dmaengine: qcom: gpi: Add lock/unlock TREs for multi-owner I2C transfers Some platforms use a QUP-based I2C controller in a configuration where the controller is shared with another system processor (described in DT using qcom,qup-multi-owner). In such setups, GPI hardware lock/unlock TREs can be used to serialize access to the controller. Add support to emit lock and unlock TREs around I2C transfers and increase the maximum TRE count to account for the additional elements. Also simplify the client interface by replacing multiple boolean fields (shared flag and message position tracking) with a single lock_action selector (acquire/release/none), as the GPI driver only needs to know whether to emit lock/unlock TREs for a given transfer. Link: https://lore.kernel.org/all/20260331114742.2896317-3-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- drivers/dma/qcom/gpi.c | 44 +++++++++++++++++++++++++++++++- include/linux/dma/qcom-gpi-dma.h | 20 ++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index a5055a6273af6..1e70d2adfdff0 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -67,6 +68,14 @@ #define TRE_DMA_LEN GENMASK(23, 0) #define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0) +/* Lock TRE */ +#define TRE_LOCK BIT(0) +#define TRE_MINOR_TYPE GENMASK(19, 16) +#define TRE_MAJOR_TYPE GENMASK(23, 20) + +/* Unlock TRE */ +#define TRE_UNLOCK BIT(8) + /* Register offsets from gpi-top */ #define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k))) #define GPII_n_CH_k_CNTXT_0_EL_SIZE GENMASK(31, 24) @@ -518,7 +527,7 @@ struct gpii { bool ieob_set; }; -#define MAX_TRE 3 +#define MAX_TRE 5 struct gpi_desc { struct virt_dma_desc vd; @@ -1625,12 +1634,27 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, unsigned long flags) { struct gpi_i2c_config *i2c = chan->config; + enum gpi_lock_action lock_action = i2c->lock_action; struct device *dev = chan->gpii->gpi_dev->dev; unsigned int tre_idx = 0; dma_addr_t address; struct gpi_tre *tre; unsigned int i; + /* Optional lock TRE before transfer */ + if (lock_action == GPI_LOCK_ACQUIRE) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_LOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(0, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); + } + /* first create config tre if applicable */ if (i2c->set_config) { tre = &desc->tre[tre_idx]; @@ -1690,6 +1714,24 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, if (!(flags & DMA_PREP_INTERRUPT)) tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI); + + /* If multi-owner and this is the release boundary, chain it */ + if (i2c->lock_action == GPI_LOCK_RELEASE) + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); + } + + /* Optional unlock TRE after transfer */ + if (lock_action == GPI_LOCK_RELEASE && i2c->op != I2C_READ) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_UNLOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(1, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); } for (i = 0; i < tre_idx; i++) diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h index 332be28427e47..f10fa93713f96 100644 --- a/include/linux/dma/qcom-gpi-dma.h +++ b/include/linux/dma/qcom-gpi-dma.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef QCOM_GPI_DMA_H @@ -54,6 +55,21 @@ enum i2c_op { I2C_READ, }; +/** + * enum gpi_lock_action - request lock/unlock TRE sequencing + * @GPI_LOCK_NONE: No lock/unlock TRE requested for this transfer + * @GPI_LOCK_ACQUIRE: Emit a lock TRE before the transfer + * @GPI_LOCK_RELEASE: Emit an unlock TRE after the transfer + * + * Used by protocol drivers for multi-owner controller setups (e.g. when + * DeviceTree indicates the controller is shared via qcom,qup-multi-owner). + */ +enum gpi_lock_action { + GPI_LOCK_NONE = 0, + GPI_LOCK_ACQUIRE, + GPI_LOCK_RELEASE, +}; + /** * struct gpi_i2c_config - i2c config for peripheral * @@ -67,7 +83,8 @@ enum i2c_op { * @set_config: set peripheral config * @rx_len: receive length for buffer * @op: i2c cmd - * @multi_msg: is part of multi i2c r-w msgs + * @muli-msg: is part of multi i2c r-w msgs + * @lock_action: request lock/unlock TRE sequencing for this transfer */ struct gpi_i2c_config { u8 set_config; @@ -81,6 +98,7 @@ struct gpi_i2c_config { u32 rx_len; enum i2c_op op; bool multi_msg; + enum gpi_lock_action lock_action; }; #endif /* QCOM_GPI_DMA_H */ From 665041f9cd2f294b9fe0cbe5d13a4f1fbaa11fee Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:41 +0530 Subject: [PATCH 0346/1058] FROMLIST: soc: qcom: geni-se: Keep pinctrl active for multi-owner controllers On platforms where a GENI Serial Engine is shared with another system processor, selecting the "sleep" pinctrl state can disrupt ongoing transfers initiated by the other processor. Teach geni_se_resources_off() to skip selecting the pinctrl sleep state when the Serial Engine is marked as shared, while still allowing the rest of the resource shutdown sequence to proceed. This is required for multi-owner configurations (described via DeviceTree with qcom,qup-multi-owner on the protocol controller node). Link: https://lore.kernel.org/all/20260331114742.2896317-4-mukesh.savaliya@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Kumar Savaliya --- drivers/soc/qcom/qcom-geni-se.c | 15 +++++++++++---- include/linux/soc/qcom/geni-se.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 15636a8dc907a..cdd1edcf394c1 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -606,10 +606,17 @@ int geni_se_resources_off(struct geni_se *se) if (has_acpi_companion(se->dev)) return 0; - - ret = pinctrl_pm_select_sleep_state(se->dev); - if (ret) - return ret; + /* + * Select the "sleep" pinctrl state only when the serial engine is + * exclusively owned by this system processor. For shared controller + * configurations, another system processor may still be using the pins, + * and switching them to "sleep" can disrupt ongoing transfers. + */ + if (!se->multi_owner) { + ret = pinctrl_pm_select_sleep_state(se->dev); + if (ret) + return ret; + } geni_se_clks_off(se); return 0; diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h index c5e6ab85df099..6a8f67a5f1c83 100644 --- a/include/linux/soc/qcom/geni-se.h +++ b/include/linux/soc/qcom/geni-se.h @@ -66,6 +66,7 @@ struct geni_icc_path { * @icc_paths: Array of ICC paths for SE * @pd_list: Power domain list for managing power domains * @has_opp: Indicates if OPP is supported + * @multi_owner: True if SE is shared between multiprocessors. */ struct geni_se { void __iomem *base; @@ -78,6 +79,7 @@ struct geni_se { struct geni_icc_path icc_paths[3]; struct dev_pm_domain_list *pd_list; bool has_opp; + bool multi_owner; }; /* Common SE registers */ From 6b2a1954e10fd919fd559b2460ef69709212bd52 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:42 +0530 Subject: [PATCH 0347/1058] FROMLIST: i2c: qcom-geni: Support multi-owner controllers in GPI mode Some platforms use a QUP-based I2C controller in a configuration where the controller is shared with another system processor. In this setup the operating system must not assume exclusive ownership of the controller or its associated pins. Add support for enabling multi-owner operation when DeviceTree specifies qcom,qup-multi-owner. When enabled, mark the underlying serial engine as shared so the common GENI resource handling avoids selecting the "sleep" pinctrl state, which could disrupt transfers initiated by the other processor. For GPI mode transfers, request lock/unlock TRE sequencing from the GPI driver by setting a single lock_action selector per message, emitting lock before the first message and unlock after the last message (handling the single-message case as well). This serializes access to the shared controller without requiring message-position flags to be passed into the DMA engine layer. Link: https://lore.kernel.org/all/20260331114742.2896317-5-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- drivers/i2c/busses/i2c-qcom-geni.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index d2f5055b0b108..18da652f9939b 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -828,6 +828,14 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i if (i < num - 1) peripheral.stretch = 1; + peripheral.lock_action = GPI_LOCK_NONE; + if (gi2c->se.multi_owner) { + if (i == 0) + peripheral.lock_action = GPI_LOCK_ACQUIRE; + else if (i == num - 1) + peripheral.lock_action = GPI_LOCK_RELEASE; + } + peripheral.addr = msgs[i].addr; if (i > 0 && (!(msgs[i].flags & I2C_M_RD))) peripheral.multi_msg = false; @@ -1027,6 +1035,17 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->clk_freq_out = I2C_MAX_STANDARD_MODE_FREQ; } + if (of_property_read_bool(pdev->dev.of_node, "qcom,qup-multi-owner")) { + /* + * Multi-owner controller configuration: the controller may be + * used by another system processor. Mark the SE as shared so + * common GENI resource handling can avoid pin state changes + * that would disrupt the other user. + */ + gi2c->se.multi_owner = true; + dev_dbg(&pdev->dev, "I2C controller is shared with another system processor\n"); + } + if (has_acpi_companion(dev)) ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev)); @@ -1102,7 +1121,9 @@ static int geni_i2c_probe(struct platform_device *pdev) } if (fifo_disable) { - /* FIFO is disabled, so we can only use GPI DMA */ + /* FIFO is disabled, so we can only use GPI DMA. + * SE can be shared in GSI mode between subsystems, each SS owns a GPII. + */ gi2c->gpi_mode = true; ret = setup_gpi_dma(gi2c); if (ret) @@ -1111,6 +1132,10 @@ static int geni_i2c_probe(struct platform_device *pdev) dev_dbg(dev, "Using GPI DMA mode for I2C\n"); } else { gi2c->gpi_mode = false; + + if (gi2c->se.multi_owner) + dev_err_probe(dev, -EINVAL, "I2C sharing not supported in non GSI mode\n"); + tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se); /* I2C Master Hub Serial Elements doesn't have the HW_PARAM_0 register */ From b5270bdafdd0f4b5c6e6ae4a441d0a0adffdf254 Mon Sep 17 00:00:00 2001 From: Praveen Talari Date: Wed, 1 Jul 2026 11:27:55 +0530 Subject: [PATCH 0348/1058] FROMLIST: serial: qcom-geni: add force suspend/resume to system sleep callbacks During system sleep the hardware resources (clocks, interconnect) are not gated because the runtime-suspend callback is never invoked from the system sleep path. This prevents the platform from reaching its lowest idle state. The system sleep callbacks qcom_geni_serial_suspend() and qcom_geni_serial_resume() rely solely on uart_suspend_port() / uart_resume_port() to manage power. uart_suspend_port() drives the UART PM state machine to UART_PM_STATE_OFF, which in turn calls pm_runtime_put_sync() and eventually the runtime-suspend callback. However, if the runtime-PM usage count is still elevated at the time of system sleep (e.g. the port is held active by an open file descriptor), the runtime-suspend callback is never invoked and the hardware resources (clocks, interconnect) remain enabled across suspend, preventing the platform from reaching its lowest idle state. Fix this by calling pm_runtime_force_suspend() at the end of qcom_geni_serial_suspend() so that the runtime-suspend callback is always executed regardless of the usage count, and by calling pm_runtime_force_resume() at the start of qcom_geni_serial_resume() to restore those resources before uart_resume_port() re-opens the port. Link: https://lore.kernel.org/all/20260701-add_force_suspend_resume_to_system_sleep_callbacks-v1-1-38c9a721a462@oss.qualcomm.com/ Signed-off-by: Praveen Talari --- drivers/tty/serial/qcom_geni_serial.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 7ead87b4eb65b..ad69976555b86 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1974,6 +1974,7 @@ static int qcom_geni_serial_suspend(struct device *dev) struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; struct qcom_geni_private_data *private_data = uport->private_data; + int ret; /* * This is done so we can hit the lowest possible state in suspend @@ -1983,7 +1984,19 @@ static int qcom_geni_serial_suspend(struct device *dev) geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ACTIVE_ONLY); geni_icc_set_bw(&port->se); } - return uart_suspend_port(private_data->drv, uport); + + ret = uart_suspend_port(private_data->drv, uport); + if (ret) + return ret; + + /* + * When no_console_suspend is set the console must remain active + * across system sleep, so skip the force suspend path. + */ + if (uart_console(uport) && !uport->suspended) + return 0; + + return pm_runtime_force_suspend(dev); } static int qcom_geni_serial_resume(struct device *dev) @@ -1993,6 +2006,10 @@ static int qcom_geni_serial_resume(struct device *dev) struct uart_port *uport = &port->uport; struct qcom_geni_private_data *private_data = uport->private_data; + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + ret = uart_resume_port(private_data->drv, uport); if (uart_console(uport)) { geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS); From fedd8c628af7b28992224012386fec13483c514c Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Mon, 29 Jun 2026 19:11:40 +0530 Subject: [PATCH 0349/1058] FROMLIST: i2c: i2c-qcom-geni: serve transfers during early resume I2C transfers issued during the resume_noirq phase can fail on GENI I2C controllers. Some devices require I2C communication before their resume sequence can complete. One example is a USB Ethernet device attached through PCIe, where device configuration must be restored over I2C before PCIe link initialization can proceed. Since such accesses occur during resume_noirq(), the underlying I2C controller must be able to service transfers at that stage. However, GENI I2C transfers rely on interrupts for command completion, while IRQ handling is still suspended during early resume. Additionally, runtime PM may remain disabled until later in the resume sequence, causing pm_runtime_get_sync() to return -EACCES and preventing controller resources from being enabled. Allow the controller to operate during early resume by requesting the IRQ with IRQF_NO_SUSPEND and IRQF_EARLY_RESUME so completion interrupts can be delivered during the noirq phase. Also restore runtime PM from resume_noirq() when it is disabled and tolerate transient -EACCES failures from pm_runtime_get_sync() during the PM state transition. This enables GENI I2C transfers to complete successfully during the resume_noirq phase and allows dependent devices to finish their resume sequence. Link: https://lore.kernel.org/all/20260629134140.755193-1-mukesh.savaliya@oss.qualcomm.com/ Co-developed-by: Viken Dadhaniya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/dma/qcom/gpi.c | 3 ++- drivers/i2c/busses/i2c-qcom-geni.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 1e70d2adfdff0..6ef72dffd3307 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -624,7 +624,8 @@ static int gpi_config_interrupts(struct gpii *gpii, enum gpii_irq_settings setti if (!gpii->configured_irq) { ret = devm_request_irq(gpii->gpi_dev->dev, gpii->irq, - gpi_handle_irq, IRQF_TRIGGER_HIGH, + gpi_handle_irq, + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, "gpi-dma", gpii); if (ret < 0) { dev_err(gpii->gpi_dev->dev, "error request irq:%d ret:%d\n", diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 18da652f9939b..cb4e7446f0755 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -921,6 +921,10 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, gi2c->err = 0; reinit_completion(&gi2c->done); ret = pm_runtime_get_sync(gi2c->se.dev); + if (ret == -EACCES) { + dev_warn(gi2c->se.dev, "Runtime PM is disabled:%d\n", ret); + ret = 0; + } if (ret < 0) { dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret); pm_runtime_put_noidle(gi2c->se.dev); @@ -1064,7 +1068,8 @@ static int geni_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gi2c); /* Keep interrupts disabled initially to allow for low-power modes */ - ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, + ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, + IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, dev_name(dev), gi2c); if (ret) return dev_err_probe(dev, ret, @@ -1282,7 +1287,12 @@ static int __maybe_unused geni_i2c_resume_noirq(struct device *dev) if (ret) return ret; + /* Enforced disable_depth = 0 to actually enable runtime PM during noirq phase */ + if (!pm_runtime_enabled(dev)) + pm_runtime_enable(dev); + i2c_mark_adapter_resumed(&gi2c->adap); + return 0; } From 4bb8eddd78289eb366441ffd6669254f2006aa0e Mon Sep 17 00:00:00 2001 From: Shivnandan Kumar Date: Fri, 27 Feb 2026 16:40:51 +0530 Subject: [PATCH 0350/1058] FROMLIST: soc: qcom: icc-bwmon: Update zone1_thres_count to 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce zone1_thres_count from 16 to 3 so the driver can lower the bus vote after 3 sample windows instead of waiting for 16. The previous 16‑window delay (~64 ms) is too long at higher FPS workloads, causing delayed decision making and measurable power regression. Empirical tuning showed that lower values (e.g., 2) made bwmon behavior jittery, while higher values (4–6) were stable but less responsive and reduced power savings. A value of 3 provided the best balance: responsive enough for timely power reduction while maintaining stable bwmon operation. Significant power savings were observed across multiple use cases when reducing the threshold from 16 to 3: USECASE zone1_thres_count=16 zone1_thres_count=3 4K video playback 236.15 mA 203.15 mA Sleep 7mA 6.9mA Display (idle display) 71.95mA 67.11mA Link: https://lore.kernel.org/r/20260227111051.1789439-1-pussin@qti.qualcomm.com Signed-off-by: Shivnandan Kumar Signed-off-by: Pushpendra Singh --- drivers/soc/qcom/icc-bwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 597f9025e4228..e46975da7dba6 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -830,7 +830,7 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { static const struct icc_bwmon_data sdm845_cpu_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_HAS_GLOBAL_IRQ, .regmap_fields = sdm845_cpu_bwmon_reg_fields, @@ -849,7 +849,7 @@ static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_NEEDS_FORCE_CLEAR, .regmap_fields = sdm845_llcc_bwmon_reg_fields, From 02d3a3b9190b137a4f01fed323ee8e8f1a5cda14 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Mon, 2 Feb 2026 16:06:41 +0530 Subject: [PATCH 0351/1058] FROMLIST: soc: qcom: qmi: Print error codes in failure paths Few error paths in the qmi_interface module log a failure message but do not include the actual error code. Include the error value in the log so debugging failures becomes easier. Reviewed-by: Dmitry Baryshkov Signed-off-by: Mukesh Ojha Signed-off-by: Xin Liu Link: https://lore.kernel.org/all/20260202103641.3003867-2-mukesh.ojha@oss.qualcomm.com/ --- drivers/soc/qcom/qmi_interface.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index 16e2e24b60968..974ed2b3d611d 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -321,7 +321,7 @@ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, mutex_lock(&qmi->txn_lock); ret = idr_alloc_cyclic(&qmi->txns, txn, 0, U16_MAX, GFP_KERNEL); if (ret < 0) - pr_err("failed to allocate transaction id\n"); + pr_err("failed to allocate transaction id: %d\n", ret); txn->id = ret; mutex_unlock(&qmi->txn_lock); @@ -413,7 +413,7 @@ static void qmi_invoke_handler(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, ret = qmi_decode_message(buf, len, handler->ei, dest); if (ret < 0) - pr_err("failed to decode incoming message\n"); + pr_err("failed to decode incoming message: %d\n", ret); else handler->fn(qmi, sq, txn, dest); @@ -502,7 +502,7 @@ static void qmi_handle_message(struct qmi_handle *qmi, if (txn->dest && txn->ei) { ret = qmi_decode_message(buf, len, txn->ei, txn->dest); if (ret < 0) - pr_err("failed to decode incoming message\n"); + pr_err("failed to decode incoming message: %d\n", ret); txn->result = ret; complete(&txn->completion); @@ -661,8 +661,8 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size, if (PTR_ERR(qmi->sock) == -EAFNOSUPPORT) { ret = -EPROBE_DEFER; } else { - pr_err("failed to create QMI socket\n"); ret = PTR_ERR(qmi->sock); + pr_err("failed to create QMI socket: %d\n", ret); } goto err_destroy_wq; } @@ -766,7 +766,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi, if (qmi->sock) { ret = kernel_sendmsg(qmi->sock, &msghdr, &iv, 1, len); if (ret < 0) - pr_err("failed to send QMI message\n"); + pr_err("failed to send QMI message: %d\n", ret); } else { ret = -EPIPE; } From f9b45a5448566569877ebefe6ba8e4e54bbb6d1c Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:41 +0800 Subject: [PATCH 0352/1058] FROMLIST: ACPI/AEST: Parse the AEST table This patch introduces the creation of AEST platform devices, where each device represents a logical "error node device" grouping one or more AEST nodes from the ACPI table. Instead of relying on the optional 'error_node_device' field in the AEST table[1], this commit uses the interrupt number as the sole identifier for the parent device. This design simplifies the driver logic by providing a single, consistent mechanism for grouping nodes. The 'error_node_device' field can be unspecified, but an AEST node is always physically associated with a parent component. The interrupt number serves as a reliable proxy for this association. This approach is based on the safe assumption that distinct hardware components (e.g., SMMU, CMN, GIC) are assigned unique error interrupts and do not share them. [1]: https://developer.arm.com/documentation/den0085/latest Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-2-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- MAINTAINERS | 8 + arch/arm64/include/asm/ras.h | 15 ++ drivers/acpi/arm64/Kconfig | 11 ++ drivers/acpi/arm64/Makefile | 1 + drivers/acpi/arm64/aest.c | 311 +++++++++++++++++++++++++++++++++++ include/linux/acpi_aest.h | 56 +++++++ 6 files changed, 402 insertions(+) create mode 100644 arch/arm64/include/asm/ras.h create mode 100644 drivers/acpi/arm64/aest.c create mode 100644 include/linux/acpi_aest.h diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a99..6209f840320bb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -340,6 +340,14 @@ S: Maintained F: drivers/acpi/arm64 F: include/linux/acpi_iort.h +ACPI AEST +M: Ruidong Tian +L: linux-acpi@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Supported +F: drivers/acpi/arm64/aest.c +F: include/linux/acpi_aest.h + ACPI FOR RISC-V (ACPI/riscv) M: Sunil V L L: linux-acpi@vger.kernel.org diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h new file mode 100644 index 0000000000000..b6640b9972bfb --- /dev/null +++ b/arch/arm64/include/asm/ras.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_RAS_H +#define __ASM_RAS_H + +#include + +struct ras_ext_regs { + u64 err_fr; + u64 err_ctlr; + u64 err_status; + u64 err_addr; + u64 err_misc[4]; +}; + +#endif /* __ASM_RAS_H */ diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig index f2fd79f22e7d8..52df190356c82 100644 --- a/drivers/acpi/arm64/Kconfig +++ b/drivers/acpi/arm64/Kconfig @@ -24,3 +24,14 @@ config ACPI_APMT config ACPI_MPAM bool + +config ACPI_AEST + bool "ARM Error Source Table Support" + depends on ARM64_RAS_EXTN + + help + The Arm Error Source Table (AEST) provides details on ACPI + extensions that enable kernel-first handling of errors in a + system that supports the Armv8 RAS extensions. + + If set, the kernel will report and log hardware errors. diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index 9390b57cb5648..bad77fdbf8dd0 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_ACPI_IORT) += iort.o obj-$(CONFIG_ACPI_MPAM) += mpam.o obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o obj-$(CONFIG_ARM_AMBA) += amba.o +obj-$(CONFIG_ACPI_AEST) += aest.o obj-y += dma.o init.o obj-y += thermal_cpufreq.o diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c new file mode 100644 index 0000000000000..b8359b95f40f9 --- /dev/null +++ b/drivers/acpi/arm64/aest.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include + +#include "init.h" + +#undef pr_fmt +#define pr_fmt(fmt) "ACPI AEST: " fmt + +static struct xarray *aest_array; + +static void __init aest_init_interface(struct acpi_aest_hdr *hdr, + struct acpi_aest_node *node) +{ + struct acpi_aest_node_interface_header *interface; + + interface = ACPI_ADD_PTR(struct acpi_aest_node_interface_header, hdr, + hdr->node_interface_offset); + + node->type = hdr->type; + node->interface_hdr = interface; + + switch (interface->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: { + struct acpi_aest_node_interface_4k *interface_4k = + (struct acpi_aest_node_interface_4k *)(interface + 1); + + node->common = &interface_4k->common; + node->record_implemented = + (unsigned long *)&interface_4k->error_record_implemented; + node->status_reporting = + (unsigned long *)&interface_4k->error_status_reporting; + node->addressing_mode = + (unsigned long *)&interface_4k->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_16K: { + struct acpi_aest_node_interface_16k *interface_16k = + (struct acpi_aest_node_interface_16k *)(interface + 1); + + node->common = &interface_16k->common; + node->record_implemented = + (unsigned long *)interface_16k->error_record_implemented; + node->status_reporting = + (unsigned long *)interface_16k->error_status_reporting; + node->addressing_mode = + (unsigned long *)interface_16k->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_64K: { + struct acpi_aest_node_interface_64k *interface_64k = + (struct acpi_aest_node_interface_64k *)(interface + 1); + + node->common = &interface_64k->common; + node->record_implemented = + (unsigned long *)interface_64k->error_record_implemented; + node->status_reporting = + (unsigned long *)interface_64k->error_status_reporting; + node->addressing_mode = + (unsigned long *)interface_64k->addressing_mode; + break; + } + default: + pr_err("invalid group format: %d\n", interface->group_format); + } + + node->interrupt = ACPI_ADD_PTR(struct acpi_aest_node_interrupt_v2, hdr, + hdr->node_interrupt_offset); + + node->interrupt_count = hdr->node_interrupt_count; +} + +static struct aest_hnode *__init +acpi_aest_alloc_ahnode(struct acpi_aest_node *node, u64 error_device_id) +{ + struct aest_hnode *ahnode __free(kfree) = NULL; + + ahnode = kzalloc(sizeof(*ahnode), GFP_KERNEL); + if (!ahnode) + return NULL; + + INIT_LIST_HEAD(&ahnode->list); + ahnode->id = error_device_id; + ahnode->count = 0; + ahnode->type = node->type; + + return_ptr(ahnode); +} +static int __init acpi_aest_init_node(struct acpi_aest_hdr *aest_hdr) +{ + struct aest_hnode *ahnode; + u64 error_device_id; + struct acpi_aest_node *node; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->spec_pointer = + ACPI_ADD_PTR(void, aest_hdr, aest_hdr->node_specific_offset); + if (aest_hdr->type == ACPI_AEST_PROCESSOR_ERROR_NODE) + node->processor_spec_pointer = + ACPI_ADD_PTR(void, node->spec_pointer, + sizeof(struct acpi_aest_processor)); + + aest_init_interface(aest_hdr, node); + + if (node->interrupt_count <= 0) + return -EINVAL; + + error_device_id = node->interrupt[0].gsiv; + ahnode = xa_load(aest_array, error_device_id); + if (!ahnode) { + ahnode = acpi_aest_alloc_ahnode(node, error_device_id); + if (!ahnode) + return -ENOMEM; + xa_store(aest_array, error_device_id, ahnode, GFP_KERNEL); + } + + list_add_tail(&node->list, &ahnode->list); + ahnode->count++; + + return 0; +} + +static int __init acpi_aest_init_nodes(struct acpi_table_header *aest_table) +{ + struct acpi_aest_hdr *aest_node, *aest_end; + struct acpi_table_aest *aest; + int rc; + + aest = (struct acpi_table_aest *)aest_table; + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, + sizeof(struct acpi_table_header)); + aest_end = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, aest_table->length); + + while (aest_node < aest_end) { + if (((u64)aest_node + aest_node->length) > (u64)aest_end) { + pr_warn(FW_WARN + "AEST node pointer overflow, bad table.\n"); + return -EINVAL; + } + + rc = acpi_aest_init_node(aest_node); + if (rc) + return rc; + + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest_node, + aest_node->length); + } + + return 0; +} + +static int acpi_aest_parse_irqs(struct platform_device *pdev, + struct acpi_aest_node *anode, + struct resource *res, int *res_idx, int irqs[2]) +{ + int i; + struct acpi_aest_node_interrupt_v2 *interrupt; + int trigger, irq; + + for (i = 0; i < anode->interrupt_count; i++) { + interrupt = &anode->interrupt[i]; + if (irqs[interrupt->type]) + continue; + + trigger = (interrupt->flags & AEST_INTERRUPT_MODE) ? + ACPI_LEVEL_SENSITIVE : + ACPI_EDGE_SENSITIVE; + + irq = acpi_register_gsi(&pdev->dev, interrupt->gsiv, trigger, + ACPI_ACTIVE_HIGH); + if (irq <= 0) { + pr_err("failed to map AEST GSI %d\n", interrupt->gsiv); + return irq; + } + + res[*res_idx].start = irq; + res[*res_idx].end = irq; + res[*res_idx].flags = IORESOURCE_IRQ; + res[*res_idx].name = interrupt->type ? AEST_ERI_NAME : + AEST_FHI_NAME; + + (*res_idx)++; + + irqs[interrupt->type] = irq; + } + + return 0; +} + +DEFINE_FREE(res, struct resource *, if (_T) kfree(_T)) +static struct platform_device *__init +acpi_aest_alloc_pdev(struct aest_hnode *ahnode, int index) +{ + struct platform_device *pdev __free(platform_device_put) = + platform_device_alloc("AEST", index++); + struct resource *res __free(res); + struct acpi_aest_node *anode; + int ret, size, j, irq[AEST_MAX_INTERRUPT_PER_NODE] = { 0 }; + + if (!pdev) + return ERR_PTR(-ENOMEM); + + res = kcalloc(ahnode->count + AEST_MAX_INTERRUPT_PER_NODE, sizeof(*res), + GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + j = 0; + list_for_each_entry(anode, &ahnode->list, list) { + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SYSTEM_REGISTER) { + res[j].name = AEST_NODE_NAME; + res[j].start = anode->interface_hdr->address; + switch (anode->interface_hdr->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: + size = 4 * KB; + break; + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + size = 16 * KB; + break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + size = 64 * KB; + break; + default: + size = 4 * KB; + } + res[j].end = res[j].start + size - 1; + res[j].flags = IORESOURCE_MEM; + } + + ret = acpi_aest_parse_irqs(pdev, anode, res, &j, irq); + if (ret) + return ERR_PTR(ret); + } + + ret = platform_device_add_resources(pdev, res, j); + if (ret) + return ERR_PTR(ret); + + ret = platform_device_add_data(pdev, &ahnode, sizeof(ahnode)); + if (ret) + return ERR_PTR(ret); + + ret = platform_device_add(pdev); + if (ret) + return ERR_PTR(ret); + + return_ptr(pdev); +} +static int __init acpi_aest_alloc_pdevs(void) +{ + int ret = 0, index = 0; + struct aest_hnode *ahnode = NULL; + unsigned long i; + + xa_for_each(aest_array, i, ahnode) { + struct platform_device *pdev = + acpi_aest_alloc_pdev(ahnode, index++); + + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + break; + } + } + + return ret; +} + +static int __init acpi_aest_init(void) +{ + int ret; + + if (acpi_disabled) + return 0; + + struct acpi_table_header *aest_table __free(acpi_put_table) = + acpi_get_table_pointer(ACPI_SIG_AEST, 0); + if (IS_ERR(aest_table)) + return 0; + + aest_array = kzalloc(sizeof(struct xarray), GFP_KERNEL); + if (!aest_array) + return -ENOMEM; + + xa_init(aest_array); + + ret = acpi_aest_init_nodes(aest_table); + if (ret) { + pr_err("Failed init aest node %d\n", ret); + return ret; + } + + ret = acpi_aest_alloc_pdevs(); + if (ret) { + pr_err("Failed alloc pdev %d\n", ret); + return ret; + } + + return 0; +} +subsys_initcall_sync(acpi_aest_init); diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h new file mode 100644 index 0000000000000..53c1970e7583b --- /dev/null +++ b/include/linux/acpi_aest.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ACPI_AEST_H__ +#define __ACPI_AEST_H__ + +#include +#include + +/* AEST resource name */ +#define AEST_NODE_NAME "AEST:NODE" +#define AEST_FHI_NAME "AEST:FHI" +#define AEST_ERI_NAME "AEST:ERI" + +/* AEST interrupt */ +#define AEST_INTERRUPT_MODE BIT(0) + +#define AEST_MAX_INTERRUPT_PER_NODE 2 + +#define KB 1024 +#define MB (1024 * KB) +#define GB (1024 * MB) + +struct aest_hnode { + struct list_head list; + int count; + u32 id; + int type; +}; + +struct acpi_aest_node { + struct list_head list; + int type; + struct acpi_aest_node_interface_header *interface_hdr; + unsigned long *record_implemented; + unsigned long *status_reporting; + unsigned long *addressing_mode; + struct acpi_aest_node_interface_common *common; + union { + struct acpi_aest_processor *processor; + struct acpi_aest_memory *memory; + struct acpi_aest_smmu *smmu; + struct acpi_aest_vendor_v2 *vendor; + struct acpi_aest_gic *gic; + struct acpi_aest_pcie *pcie; + struct acpi_aest_proxy *proxy; + void *spec_pointer; + }; + union { + struct acpi_aest_processor_cache *cache; + struct acpi_aest_processor_tlb *tlb; + struct acpi_aest_processor_generic *generic; + void *processor_spec_pointer; + }; + struct acpi_aest_node_interrupt_v2 *interrupt; + int interrupt_count; +}; +#endif /* __ACPI_AEST_H__ */ From 69496b78b2bff1c884a73a3a4434340195bcb06a Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:42 +0800 Subject: [PATCH 0353/1058] FROMLIST: ras: AEST: Add probe/remove for AEST driver Parse register information from the AEST table in the probe function, create corresponding structures, and mappings AEST record. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-3-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- MAINTAINERS | 2 + drivers/ras/Kconfig | 1 + drivers/ras/Makefile | 1 + drivers/ras/aest/Kconfig | 17 +++ drivers/ras/aest/Makefile | 5 + drivers/ras/aest/aest-core.c | 217 +++++++++++++++++++++++++++++++++++ drivers/ras/aest/aest.h | 124 ++++++++++++++++++++ include/linux/acpi_aest.h | 9 ++ 8 files changed, 376 insertions(+) create mode 100644 drivers/ras/aest/Kconfig create mode 100644 drivers/ras/aest/Makefile create mode 100644 drivers/ras/aest/aest-core.c create mode 100644 drivers/ras/aest/aest.h diff --git a/MAINTAINERS b/MAINTAINERS index 6209f840320bb..6139e5257c2b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -345,7 +345,9 @@ M: Ruidong Tian L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org S: Supported +F: arch/arm64/include/asm/ras.h F: drivers/acpi/arm64/aest.c +F: drivers/ras/aest/ F: include/linux/acpi_aest.h ACPI FOR RISC-V (ACPI/riscv) diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig index fc4f4bb94a4c6..61a2a05d9c949 100644 --- a/drivers/ras/Kconfig +++ b/drivers/ras/Kconfig @@ -33,6 +33,7 @@ if RAS source "arch/x86/ras/Kconfig" source "drivers/ras/amd/atl/Kconfig" +source "drivers/ras/aest/Kconfig" config RAS_FMPM tristate "FRU Memory Poison Manager" diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile index 11f95d59d3972..72411ee9deafd 100644 --- a/drivers/ras/Makefile +++ b/drivers/ras/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_RAS_CEC) += cec.o obj-$(CONFIG_RAS_FMPM) += amd/fmpm.o obj-y += amd/atl/ +obj-y += aest/ diff --git a/drivers/ras/aest/Kconfig b/drivers/ras/aest/Kconfig new file mode 100644 index 0000000000000..0b09a5d5acce3 --- /dev/null +++ b/drivers/ras/aest/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# ARM Error Source Table Support +# +# Copyright (c) 2025, Alibaba Group. +# + +config AEST + tristate "ARM AEST Driver" + depends on ACPI_AEST && RAS + + help + The Arm Error Source Table (AEST) provides details on ACPI + extensions that enable kernel-first handling of errors in a + system that supports the Armv8 RAS extensions. + + If set, the kernel will report and log hardware errors. diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile new file mode 100644 index 0000000000000..a6ba7e36fb432 --- /dev/null +++ b/drivers/ras/aest/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_AEST) += aest.o + +aest-y := aest-core.o diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c new file mode 100644 index 0000000000000..c7ef6c13fd440 --- /dev/null +++ b/drivers/ras/aest/aest-core.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include + +#include "aest.h" + +DEFINE_PER_CPU(struct aest_device, percpu_adev); + +#undef pr_fmt +#define pr_fmt(fmt) "AEST: " fmt + +static int aest_init_record(struct aest_record *record, int i, + struct aest_node *node) +{ + struct device *dev = node->adev->dev; + + record->name = devm_kasprintf(dev, GFP_KERNEL, "record%d", i); + if (!record->name) + return -ENOMEM; + + if (node->base) + record->regs_base = + node->base + sizeof(struct ras_ext_regs) * i; + + record->addressing_mode = test_bit(i, node->info->addressing_mode); + record->index = i; + record->node = node; + + aest_record_dbg(record, "base: %p, index: %d, address mode: %x\n", + record->regs_base, record->index, + record->addressing_mode); + return 0; +} + +static void aest_device_remove(struct platform_device *pdev) +{ + platform_set_drvdata(pdev, NULL); +} + +static char *alloc_aest_node_name(struct aest_node *node) +{ + char *name; + + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "%s.%d", + aest_node_name[node->type], + node->info->processor->processor_id); + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + case ACPI_AEST_SMMU_ERROR_NODE: + case ACPI_AEST_VENDOR_ERROR_NODE: + case ACPI_AEST_GIC_ERROR_NODE: + case ACPI_AEST_PCIE_ERROR_NODE: + case ACPI_AEST_PROXY_ERROR_NODE: + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "%s.%llx", + aest_node_name[node->type], + node->info->interface_hdr->address); + break; + default: + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "Unknown"); + } + + return name; +} + +static int aest_node_set_errgsr(struct aest_device *adev, + struct aest_node *node) +{ + struct acpi_aest_node *anode = node->info; + u64 errgsr_base = anode->common->error_group_register_base; + + if (anode->interface_hdr->type != ACPI_AEST_NODE_MEMORY_MAPPED) + return 0; + + if (!node->base) + return 0; + + if (!(anode->interface_hdr->flags & AEST_XFACE_FLAG_ERROR_GROUP)) { + node->errgsr = node->base + ERXGROUP; + return 0; + } + + if (!errgsr_base) + return -EINVAL; + + node->errgsr = devm_ioremap(adev->dev, errgsr_base, PAGE_SIZE); + if (!node->errgsr) + return -ENOMEM; + + return 0; +} + +static int aest_init_node(struct aest_device *adev, struct aest_node *node, + struct acpi_aest_node *anode) +{ + int i, ret; + u64 address; + + node->adev = adev; + node->info = anode; + node->type = anode->type; + node->name = alloc_aest_node_name(node); + if (!node->name) + return -ENOMEM; + node->record_implemented = anode->record_implemented; + node->status_reporting = anode->status_reporting; + + address = anode->interface_hdr->address; + if (address) { + node->base = devm_ioremap(adev->dev, address, PAGE_SIZE); + if (!node->base) + return -ENOMEM; + } + + ret = aest_node_set_errgsr(adev, node); + if (ret) + return ret; + + node->record_count = anode->interface_hdr->error_record_count; + node->records = devm_kcalloc(adev->dev, node->record_count, + sizeof(struct aest_record), GFP_KERNEL); + if (!node->records) + return -ENOMEM; + + for (i = 0; i < node->record_count; i++) { + ret = aest_init_record(&node->records[i], i, node); + if (ret) + return ret; + } + aest_node_dbg(node, "%d records, base: %llx, errgsr: %llx\n", + node->record_count, (u64)node->base, (u64)node->errgsr); + return 0; +} + +static int aest_init_nodes(struct aest_device *adev, struct aest_hnode *ahnode) +{ + struct acpi_aest_node *anode; + struct aest_node *node; + int ret, i = 0; + + adev->node_cnt = ahnode->count; + adev->nodes = devm_kcalloc(adev->dev, adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!adev->nodes) + return -ENOMEM; + + list_for_each_entry(anode, &ahnode->list, list) { + adev->type = anode->type; + + node = &adev->nodes[i++]; + ret = aest_init_node(adev, node, anode); + if (ret) + return ret; + } + + return 0; +} + +static int aest_device_probe(struct platform_device *pdev) +{ + int ret; + struct aest_device *adev; + struct aest_hnode *ahnode; + + ahnode = *((struct aest_hnode **)pdev->dev.platform_data); + if (!ahnode) + return -ENODEV; + + adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + adev->dev = &pdev->dev; + adev->id = pdev->id; + aest_set_name(adev, ahnode); + ret = aest_init_nodes(adev, ahnode); + if (ret) + return ret; + + platform_set_drvdata(pdev, adev); + + aest_dev_dbg(adev, "Node cnt: %x, id: %x\n", adev->node_cnt, adev->id); + + return 0; +} + +static struct platform_driver aest_driver = { + .driver = { + .name = "AEST", + }, + .probe = aest_device_probe, + .remove = aest_device_remove, +}; + +static int __init aest_init(void) +{ + return platform_driver_register(&aest_driver); +} +module_init(aest_init); + +static void __exit aest_exit(void) +{ + platform_driver_unregister(&aest_driver); +} +module_exit(aest_exit); + +MODULE_DESCRIPTION("ARM AEST Driver"); +MODULE_AUTHOR("Ruidong Tian "); +MODULE_LICENSE("GPL"); diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h new file mode 100644 index 0000000000000..d918240c3f57e --- /dev/null +++ b/drivers/ras/aest/aest.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include + +#define MAX_GSI_PER_NODE 2 + +#define aest_dev_err(__adev, format, ...) \ + dev_err((__adev)->dev, format, ##__VA_ARGS__) +#define aest_dev_info(__adev, format, ...) \ + dev_info((__adev)->dev, format, ##__VA_ARGS__) +#define aest_dev_dbg(__adev, format, ...) \ + dev_dbg((__adev)->dev, format, ##__VA_ARGS__) + +#define aest_node_err(__node, format, ...) \ + dev_err((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define aest_node_info(__node, format, ...) \ + dev_info((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define aest_node_dbg(__node, format, ...) \ + dev_dbg((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) + +#define aest_record_err(__record, format, ...) \ + dev_err((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define aest_record_info(__record, format, ...) \ + dev_info((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define aest_record_dbg(__record, format, ...) \ + dev_dbg((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) + +#define ERXGROUP 0xE00 + +struct aest_record { + char *name; + int index; + void __iomem *regs_base; + + /* + * This bit specifies the addressing mode to populate the ERR_ADDR + * register: + * 0b: Error record reports System Physical Addresses (SPA) in + * the ERR_ADDR register. + * 1b: Error record reports error node-specific Logical Addresses(LA) + * in the ERR_ADD register. OS must use other means to translate + * the reported LA into SPA + */ + int addressing_mode; + struct aest_node *node; +}; + +struct aest_node { + char *name; + u8 type; + void *errgsr; + void *base; + + /* + * This bitmap indicates which of the error records within this error + * node must be polled for error status. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n needs to be polled. + * Bit[n] = 1b: Error record at index n do not needs to be polled. + */ + unsigned long *record_implemented; + /* + * This bitmap indicates which of the error records within this error + * node support error status reporting using ERRGSR register. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n supports error status reporting + * through ERRGSR.S. + * Bit[n] = 1b: Error record at index n does not support error reporting + * through the ERRGSR.S bit If this error record is + * implemented, then it must be polled explicitly for + * error events. + */ + unsigned long *status_reporting; + + struct aest_device *adev; + struct acpi_aest_node *info; + + int record_count; + struct aest_record *records; +}; + +struct aest_device { + struct device *dev; + u32 type; + int node_cnt; + struct aest_node *nodes; + u32 id; +}; + +static const char *const aest_node_name[] = { + [ACPI_AEST_PROCESSOR_ERROR_NODE] = "processor", + [ACPI_AEST_MEMORY_ERROR_NODE] = "memory", + [ACPI_AEST_SMMU_ERROR_NODE] = "smmu", + [ACPI_AEST_VENDOR_ERROR_NODE] = "vendor", + [ACPI_AEST_GIC_ERROR_NODE] = "gic", + [ACPI_AEST_PCIE_ERROR_NODE] = "pcie", + [ACPI_AEST_PROXY_ERROR_NODE] = "proxy", +}; + +static inline int aest_set_name(struct aest_device *adev, + struct aest_hnode *ahnode) +{ + adev->dev->init_name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s%d", + aest_node_name[ahnode->type], + adev->id); + if (!adev->dev->init_name) + return -ENOMEM; + + return 0; +} diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index 53c1970e7583b..77187ce43d44b 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -15,6 +15,15 @@ #define AEST_MAX_INTERRUPT_PER_NODE 2 +/* AEST interface */ +#define AEST_XFACE_FLAG_SHARED (1 << 0) +#define AEST_XFACE_FLAG_CLEAR_MISC (1 << 1) +#define AEST_XFACE_FLAG_ERROR_DEVICE (1 << 2) +#define AEST_XFACE_FLAG_AFFINITY (1 << 3) +#define AEST_XFACE_FLAG_ERROR_GROUP (1 << 4) +#define AEST_XFACE_FLAG_FAULT_INJECT (1 << 5) +#define AEST_XFACE_FLAG_INT_CONFIG (1 << 6) + #define KB 1024 #define MB (1024 * KB) #define GB (1024 * MB) From da1f6cdb4ccf12a538d2da6c0a18b756ec5169c8 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:43 +0800 Subject: [PATCH 0354/1058] FROMLIST: ras: AEST: support different group format Support for various AEST group formats allows for flexible configuration of AEST node address space sizes and maximum record counts per group. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-4-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 6 ++++-- drivers/ras/aest/aest.h | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index c7ef6c13fd440..acebb293ac75a 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -84,7 +84,7 @@ static int aest_node_set_errgsr(struct aest_device *adev, return 0; if (!(anode->interface_hdr->flags & AEST_XFACE_FLAG_ERROR_GROUP)) { - node->errgsr = node->base + ERXGROUP; + node->errgsr = node->base + node->group->errgsr_offset; return 0; } @@ -112,10 +112,12 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, return -ENOMEM; node->record_implemented = anode->record_implemented; node->status_reporting = anode->status_reporting; + node->group = &aest_group_config[anode->interface_hdr->group_format]; address = anode->interface_hdr->address; if (address) { - node->base = devm_ioremap(adev->dev, address, PAGE_SIZE); + node->base = + devm_ioremap(adev->dev, address, node->group->size); if (!node->base) return -ENOMEM; } diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index d918240c3f57e..3250675e99b77 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -37,7 +37,15 @@ dev_dbg((__record)->node->adev->dev, "%s: %s: " format, \ (__record)->node->name, (__record)->name, ##__VA_ARGS__) -#define ERXGROUP 0xE00 +#define ERXGROUP_4K_OFFSET 0xE00 +#define ERXGROUP_16K_OFFSET 0x3800 +#define ERXGROUP_64K_OFFSET 0xE000 +#define ERXGROUP_4K_SIZE (4 * KB) +#define ERXGROUP_16K_SIZE (16 * KB) +#define ERXGROUP_64K_SIZE (64 * KB) +#define ERXGROUP_4K_ERRGSR_NUM 1 +#define ERXGROUP_16K_ERRGSR_NUM 4 +#define ERXGROUP_64K_ERRGSR_NUM 14 struct aest_record { char *name; @@ -57,6 +65,34 @@ struct aest_record { struct aest_node *node; }; +struct aest_group { + int type; + int errgsr_num; + size_t size; + u64 errgsr_offset; +}; + +static const struct aest_group aest_group_config[] = { + [ACPI_AEST_NODE_GROUP_FORMAT_4K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_4K, + .errgsr_num = ERXGROUP_4K_ERRGSR_NUM, + .size = ERXGROUP_4K_SIZE, + .errgsr_offset = ERXGROUP_4K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_16K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_16K, + .errgsr_num = ERXGROUP_16K_ERRGSR_NUM, + .size = ERXGROUP_16K_SIZE, + .errgsr_offset = ERXGROUP_16K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_64K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_64K, + .errgsr_num = ERXGROUP_64K_ERRGSR_NUM, + .size = ERXGROUP_64K_SIZE, + .errgsr_offset = ERXGROUP_64K_OFFSET, + }, +}; + struct aest_node { char *name; u8 type; @@ -86,6 +122,7 @@ struct aest_node { */ unsigned long *status_reporting; + const struct aest_group *group; struct aest_device *adev; struct acpi_aest_node *info; From 44455df4d88705d4744410f8a894fe30705d5200 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:44 +0800 Subject: [PATCH 0355/1058] FROMLIST: ras: AEST: Unify the read/write interface for system and MMIO register Use record_read/write to simultaneously read and write system registers and MMIO registers while maintaining code conciseness. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-5-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 1 + drivers/ras/aest/aest.h | 94 ++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index acebb293ac75a..f4a5119dc513b 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -29,6 +29,7 @@ static int aest_init_record(struct aest_record *record, int i, record->regs_base = node->base + sizeof(struct ras_ext_regs) * i; + record->access = &aest_access[node->info->interface_hdr->type]; record->addressing_mode = test_bit(i, node->info->addressing_mode); record->index = i; record->node = node; diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 3250675e99b77..31131cce99281 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -10,6 +10,11 @@ #define MAX_GSI_PER_NODE 2 +#define record_read(record, offset) \ + record->access->read(record->regs_base, offset) +#define record_write(record, offset, val) \ + record->access->write(record->regs_base, offset, val) + #define aest_dev_err(__adev, format, ...) \ dev_err((__adev)->dev, format, ##__VA_ARGS__) #define aest_dev_info(__adev, format, ...) \ @@ -47,6 +52,20 @@ #define ERXGROUP_16K_ERRGSR_NUM 4 #define ERXGROUP_64K_ERRGSR_NUM 14 +#define ERXFR 0x0 +#define ERXCTLR 0x8 +#define ERXSTATUS 0x10 +#define ERXADDR 0x18 +#define ERXMISC0 0x20 +#define ERXMISC1 0x28 +#define ERXMISC2 0x30 +#define ERXMISC3 0x38 + +struct aest_access { + u64 (*read)(void *base, u32 offset); + void (*write)(void *base, u32 offset, u64 val); +}; + struct aest_record { char *name; int index; @@ -63,6 +82,7 @@ struct aest_record { */ int addressing_mode; struct aest_node *node; + const struct aest_access *access; }; struct aest_group { @@ -159,3 +179,77 @@ static inline int aest_set_name(struct aest_device *adev, return 0; } + +#define CASE_READ(res, x) \ + case (x): { \ + res = read_sysreg_s(SYS_##x##_EL1); \ + break; \ + } + +#define CASE_WRITE(val, x) \ + case (x): { \ + write_sysreg_s((val), SYS_##x##_EL1); \ + break; \ + } + +static inline u64 aest_sysreg_read(void *__unused, u32 offset) +{ + u64 res; + + switch (offset) { + CASE_READ(res, ERXFR) + CASE_READ(res, ERXCTLR) + CASE_READ(res, ERXSTATUS) + CASE_READ(res, ERXADDR) + CASE_READ(res, ERXMISC0) + CASE_READ(res, ERXMISC1) + CASE_READ(res, ERXMISC2) + CASE_READ(res, ERXMISC3) + default : + res = 0; + } + return res; +} + +static inline void aest_sysreg_write(void *base, u32 offset, u64 val) +{ + switch (offset) { + CASE_WRITE(val, ERXFR) + CASE_WRITE(val, ERXCTLR) + CASE_WRITE(val, ERXSTATUS) + CASE_WRITE(val, ERXADDR) + CASE_WRITE(val, ERXMISC0) + CASE_WRITE(val, ERXMISC1) + CASE_WRITE(val, ERXMISC2) + CASE_WRITE(val, ERXMISC3) + default : + return; + } +} + +static inline u64 aest_iomem_read(void *base, u32 offset) +{ + return readq_relaxed(base + offset); +} + +static inline void aest_iomem_write(void *base, u32 offset, u64 val) +{ + writeq_relaxed(val, base + offset); +} + +/* access type is decided by AEST interface type. */ +static const struct aest_access aest_access[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = aest_sysreg_read, + .write = aest_sysreg_write, + }, + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = aest_iomem_read, + .write = aest_iomem_write, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = aest_iomem_read, + .write = aest_iomem_write, + }, + { } +}; From 16d81b8edded8f8d06311fc1655761d22b4a60c8 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:45 +0800 Subject: [PATCH 0356/1058] FROMLIST: ras: AEST: Probe RAS system architecture version The RAS version of a component can be probed via its ERRDEVARCH register. In cases where a component (e.g., SMMU) does not implement an ERRDEVARCH register, the driver falls back to using the RAS version of the Processing Element (PE). Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-6-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- arch/arm64/include/asm/ras.h | 3 +++ drivers/ras/aest/aest-core.c | 22 ++++++++++++++++++++++ drivers/ras/aest/aest.h | 3 +++ 3 files changed, 28 insertions(+) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index b6640b9972bfb..da7c441252feb 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -4,6 +4,9 @@ #include +/* ERRDEVARCH */ +#define ERRDEVARCH_REV GENMASK(19, 16) + struct ras_ext_regs { u64 err_fr; u64 err_ctlr; diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index f4a5119dc513b..84b2fb8127ffc 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -16,6 +16,27 @@ DEFINE_PER_CPU(struct aest_device, percpu_adev); #undef pr_fmt #define pr_fmt(fmt) "AEST: " fmt +static int get_aest_node_ver(struct aest_node *node) +{ + u64 reg; + void *devarch_base; + + if (node->type == ACPI_AEST_GIC_ERROR_NODE) { + devarch_base = ioremap(node->info->interface_hdr->address + + GIC_ERRDEVARCH, + PAGE_SIZE); + if (!devarch_base) + return 0; + + reg = readl_relaxed(devarch_base); + iounmap(devarch_base); + + return FIELD_GET(ERRDEVARCH_REV, reg); + } + + return FIELD_GET(ID_AA64PFR0_EL1_RAS_MASK, read_cpuid(ID_AA64PFR0_EL1)); +} + static int aest_init_record(struct aest_record *record, int i, struct aest_node *node) { @@ -108,6 +129,7 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, node->adev = adev; node->info = anode; node->type = anode->type; + node->version = get_aest_node_ver(node); node->name = alloc_aest_node_name(node); if (!node->name) return -ENOMEM; diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 31131cce99281..bf0b9a49fdaa2 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -61,6 +61,8 @@ #define ERXMISC2 0x30 #define ERXMISC3 0x38 +#define GIC_ERRDEVARCH 0xFFBC + struct aest_access { u64 (*read)(void *base, u32 offset); void (*write)(void *base, u32 offset, u64 val); @@ -141,6 +143,7 @@ struct aest_node { * error events. */ unsigned long *status_reporting; + int version; const struct aest_group *group; struct aest_device *adev; From 4789362899facc68daac6467bb95595f0c0bd5b6 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:46 +0800 Subject: [PATCH 0357/1058] FROMLIST: ras: AEST: Support RAS Common Fault Injection Model Extension Add inject register descripted in Common Fault Injection Model Extension. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-7-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 15 ++++++++++++++- drivers/ras/aest/aest.h | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 84b2fb8127ffc..1218ae51079cf 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -124,7 +124,7 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, struct acpi_aest_node *anode) { int i, ret; - u64 address; + u64 address, flags; node->adev = adev; node->info = anode; @@ -145,6 +145,19 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, return -ENOMEM; } + flags = anode->interface_hdr->flags; + address = node->info->common->fault_inject_register_base; + if ((flags & AEST_XFACE_FLAG_FAULT_INJECT) && address) { + if (address - anode->interface_hdr->address < node->group->size) + node->inj = node->base + + (address - anode->interface_hdr->address); + else { + node->inj = devm_ioremap(adev->dev, address, PAGE_SIZE); + if (!node->inj) + return -ENOMEM; + } + } + ret = aest_node_set_errgsr(adev, node); if (ret) return ret; diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index bf0b9a49fdaa2..505ecd9635bcb 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -60,6 +60,9 @@ #define ERXMISC1 0x28 #define ERXMISC2 0x30 #define ERXMISC3 0x38 +#define ERXPFGF 0x800 +#define ERXPFGCTL 0x808 +#define ERXPFGCDN 0x810 #define GIC_ERRDEVARCH 0xFFBC @@ -120,6 +123,7 @@ struct aest_node { u8 type; void *errgsr; void *base; + void *inj; /* * This bitmap indicates which of the error records within this error @@ -208,6 +212,9 @@ static inline u64 aest_sysreg_read(void *__unused, u32 offset) CASE_READ(res, ERXMISC1) CASE_READ(res, ERXMISC2) CASE_READ(res, ERXMISC3) + CASE_READ(res, ERXPFGF) + CASE_READ(res, ERXPFGCTL) + CASE_READ(res, ERXPFGCDN) default : res = 0; } @@ -225,6 +232,9 @@ static inline void aest_sysreg_write(void *base, u32 offset, u64 val) CASE_WRITE(val, ERXMISC1) CASE_WRITE(val, ERXMISC2) CASE_WRITE(val, ERXMISC3) + CASE_WRITE(val, ERXPFGF) + CASE_WRITE(val, ERXPFGCTL) + CASE_WRITE(val, ERXPFGCDN) default : return; } From 0d9e6ba3ad3c929ce1b78f833f62ef919d73ec9b Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:47 +0800 Subject: [PATCH 0358/1058] FROMLIST: ras: AEST: Support CE threshold of error record The CE threshold defines the number of Correctable Errors (CE) that must occur in a record before triggering an interrupt. Error records support multiple threshold configurations, including 8B, 16B, and 32B. This patch detects the supported threshold settings for error records and sets the default threshold to 1, ensuring an interrupt is generated for every CE occurrence. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-8-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- arch/arm64/include/asm/ras.h | 41 ++++++++++++++++++++ drivers/ras/aest/aest-core.c | 74 ++++++++++++++++++++++++++++++++++++ drivers/ras/aest/aest.h | 17 +++++++++ include/linux/acpi_aest.h | 3 ++ 4 files changed, 135 insertions(+) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index da7c441252feb..6c51d27520c00 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -4,9 +4,50 @@ #include +/* ERRFR */ +#define ERR_FR_CE GENMASK_ULL(54, 53) +#define ERR_FR_RP BIT(15) +#define ERR_FR_CEC GENMASK_ULL(14, 12) + +#define ERR_FR_RP_SINGLE_COUNTER 0 +#define ERR_FR_RP_DOUBLE_COUNTER 1 + +#define ERR_FR_CEC_0B_COUNTER 0 +#define ERR_FR_CEC_8B_COUNTER BIT(1) +#define ERR_FR_CEC_16B_COUNTER BIT(2) + +/* ERRMISC0 */ + +/* ERRFR.CEC == 0b010, ERRFR.RP == 0 */ +#define ERR_MISC0_8B_OF BIT(39) +#define ERR_MISC0_8B_CEC GENMASK_ULL(38, 32) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 0 */ +#define ERR_MISC0_16B_OF BIT(47) +#define ERR_MISC0_16B_CEC GENMASK_ULL(46, 32) + +#define ERR_MISC0_CEC_SHIFT 31 + +#define ERR_8B_CEC_MAX (ERR_MISC0_8B_CEC >> ERR_MISC0_CEC_SHIFT) +#define ERR_16B_CEC_MAX (ERR_MISC0_16B_CEC >> ERR_MISC0_CEC_SHIFT) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 1 */ +#define ERR_MISC0_16B_OFO BIT(63) +#define ERR_MISC0_16B_CECO GENMASK_ULL(62, 48) +#define ERR_MISC0_16B_OFR BIT(47) +#define ERR_MISC0_16B_CECR GENMASK_ULL(46, 32) + /* ERRDEVARCH */ #define ERRDEVARCH_REV GENMASK(19, 16) +enum ras_ce_threshold { + RAS_CE_THRESHOLD_0B, + RAS_CE_THRESHOLD_8B, + RAS_CE_THRESHOLD_16B, + RAS_CE_THRESHOLD_32B, + UNKNOWN, +}; + struct ras_ext_regs { u64 err_fr; u64 err_ctlr; diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 1218ae51079cf..5cfe91a6d72a9 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -16,6 +16,79 @@ DEFINE_PER_CPU(struct aest_device, percpu_adev); #undef pr_fmt #define pr_fmt(fmt) "AEST: " fmt +static enum ras_ce_threshold aest_get_ce_threshold(struct aest_record *record) +{ + u64 err_fr, err_fr_cec, err_fr_rp = -1; + + err_fr = record_read(record, ERXFR); + err_fr_cec = FIELD_GET(ERR_FR_CEC, err_fr); + err_fr_rp = FIELD_GET(ERR_FR_RP, err_fr); + + if (err_fr_cec == ERR_FR_CEC_0B_COUNTER) + return RAS_CE_THRESHOLD_0B; + else if (err_fr_rp == ERR_FR_RP_DOUBLE_COUNTER) + return RAS_CE_THRESHOLD_32B; + else if (err_fr_cec == ERR_FR_CEC_8B_COUNTER) + return RAS_CE_THRESHOLD_8B; + else if (err_fr_cec == ERR_FR_CEC_16B_COUNTER) + return RAS_CE_THRESHOLD_16B; + else + return UNKNOWN; +} + +static const struct ce_threshold_info ce_info[] = { + [RAS_CE_THRESHOLD_0B] = { 0 }, + [RAS_CE_THRESHOLD_8B] = { + .max_count = ERR_8B_CEC_MAX, + .mask = ERR_MISC0_8B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, + [RAS_CE_THRESHOLD_16B] = { + .max_count = ERR_16B_CEC_MAX, + .mask = ERR_MISC0_16B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, +}; + +static void aest_set_ce_threshold(struct aest_record *record) +{ + u64 err_misc0; + struct ce_threshold *ce = &record->ce; + const struct ce_threshold_info *info; + + record->threshold_type = aest_get_ce_threshold(record); + + switch (record->threshold_type) { + case RAS_CE_THRESHOLD_0B: + aest_record_dbg(record, "do not support CE threshold!\n"); + return; + case RAS_CE_THRESHOLD_8B: + aest_record_dbg(record, "support 8 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_16B: + aest_record_dbg(record, "support 16 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_32B: + aest_record_dbg(record, "not support 32 bit CE threshold!\n"); + break; + default: + aest_record_dbg(record, "Unknown misc0 ce threshold!\n"); + } + + err_misc0 = record_read(record, ERXMISC0); + info = &ce_info[record->threshold_type]; + ce->info = info; + + // Default CE threshold is 1. + ce->count = info->max_count; + ce->threshold = DEFAULT_CE_THRESHOLD; + ce->reg_val = err_misc0 | info->mask; + + record_write(record, ERXMISC0, ce->reg_val); + aest_record_dbg(record, "CE threshold is %llx, controlled by Kernel", + ce->threshold); +} + static int get_aest_node_ver(struct aest_node *node) { u64 reg; @@ -54,6 +127,7 @@ static int aest_init_record(struct aest_record *record, int i, record->addressing_mode = test_bit(i, node->info->addressing_mode); record->index = i; record->node = node; + aest_set_ce_threshold(record); aest_record_dbg(record, "base: %p, index: %d, address mode: %x\n", record->regs_base, record->index, diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 505ecd9635bcb..85eeed79bcbee 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -9,6 +9,7 @@ #include #define MAX_GSI_PER_NODE 2 +#define DEFAULT_CE_THRESHOLD 1 #define record_read(record, offset) \ record->access->read(record->regs_base, offset) @@ -71,6 +72,19 @@ struct aest_access { void (*write)(void *base, u32 offset, u64 val); }; +struct ce_threshold_info { + const u64 max_count; + const u64 mask; + const u64 shift; +}; + +struct ce_threshold { + const struct ce_threshold_info *info; + u64 count; + u64 threshold; + u64 reg_val; +}; + struct aest_record { char *name; int index; @@ -88,6 +102,9 @@ struct aest_record { int addressing_mode; struct aest_node *node; const struct aest_access *access; + + struct ce_threshold ce; + enum ras_ce_threshold threshold_type; }; struct aest_group { diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index 77187ce43d44b..a7898c643896e 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -13,6 +13,9 @@ /* AEST interrupt */ #define AEST_INTERRUPT_MODE BIT(0) +#define AEST_INTERRUPT_FHI_UE_SUPPORT BIT(0) +#define AEST_INTERRUPT_FHI_UE_NO_SUPPORT BIT(1) + #define AEST_MAX_INTERRUPT_PER_NODE 2 /* AEST interface */ From 55c67dd8a40244ad3e5ae9f48ffe4abafd449ec0 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:48 +0800 Subject: [PATCH 0359/1058] FROMLIST: ras: AEST: Enable and register IRQs The interrupt numbers for certain error records may be explicitly programmed into their configuration register. And for PPIs, each core will maintains its own copy of the aest_device structure. Given that handling RAS errors entails complex processes such as EDAC and memory_failure, all handling is deferred to and handled within a bottom-half context. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-9-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- arch/arm64/include/asm/ras.h | 36 +++ drivers/ras/aest/aest-core.c | 531 ++++++++++++++++++++++++++++++++++- drivers/ras/aest/aest.h | 56 ++++ include/linux/acpi_aest.h | 7 + include/linux/ras.h | 8 + 5 files changed, 637 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index 6c51d27520c00..02cf15278d9ff 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -2,6 +2,7 @@ #ifndef __ASM_RAS_H #define __ASM_RAS_H +#include #include /* ERRFR */ @@ -37,6 +38,41 @@ #define ERR_MISC0_16B_OFR BIT(47) #define ERR_MISC0_16B_CECR GENMASK_ULL(46, 32) +/* ERRSTATUS */ +#define ERR_STATUS_AV BIT(31) +#define ERR_STATUS_V BIT(30) +#define ERR_STATUS_UE BIT(29) +#define ERR_STATUS_ER BIT(28) +#define ERR_STATUS_OF BIT(27) +#define ERR_STATUS_MV BIT(26) +#define ERR_STATUS_CE (BIT(25) | BIT(24)) +#define ERR_STATUS_DE BIT(23) +#define ERR_STATUS_PN BIT(22) +#define ERR_STATUS_UET (BIT(21) | BIT(20)) +#define ERR_STATUS_CI BIT(19) +#define ERR_STATUS_IERR GENMASK_ULL(15, 8) +#define ERR_STATUS_SERR GENMASK_ULL(7, 0) + +/* Theses bits are write-one-to-clear */ +#define ERR_STATUS_W1TC \ + (ERR_STATUS_AV | ERR_STATUS_V | ERR_STATUS_UE | ERR_STATUS_ER | \ + ERR_STATUS_OF | ERR_STATUS_MV | ERR_STATUS_CE | ERR_STATUS_DE | \ + ERR_STATUS_PN | ERR_STATUS_UET | ERR_STATUS_CI) + +#define ERR_STATUS_UET_UC 0 +#define ERR_STATUS_UET_UEU 1 +#define ERR_STATUS_UET_UEO 2 +#define ERR_STATUS_UET_UER 3 + +/* ERRADDR */ +#define ERR_ADDR_AI BIT(61) +#define ERR_ADDR_PADDR GENMASK_ULL(55, 0) + +/* ERRCTLR */ +#define ERR_CTLR_CFI BIT(8) +#define ERR_CTLR_FI BIT(3) +#define ERR_CTLR_UI BIT(2) + /* ERRDEVARCH */ #define ERRDEVARCH_REV GENMASK(19, 16) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 5cfe91a6d72a9..5ec0ba38f51b4 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -5,8 +5,11 @@ * Copyright (c) 2025, Alibaba Group. */ +#include +#include #include #include +#include #include #include "aest.h" @@ -16,6 +19,439 @@ DEFINE_PER_CPU(struct aest_device, percpu_adev); #undef pr_fmt #define pr_fmt(fmt) "AEST: " fmt +/* + * This memory pool is only to be used to save AEST node in AEST irq context. + * There can be 500 AEST node at most. + */ +#define AEST_NODE_ALLOCED_MAX 500 + +#define AEST_LOG_PREFIX_BUFFER 64 + +BLOCKING_NOTIFIER_HEAD(aest_decoder_chain); + +static void aest_print(struct aest_event *event) +{ + static atomic_t seqno = { 0 }; + unsigned int curr_seqno; + char pfx_seq[AEST_LOG_PREFIX_BUFFER]; + int index; + struct ras_ext_regs *regs; + + curr_seqno = atomic_inc_return(&seqno); + snprintf(pfx_seq, sizeof(pfx_seq), "{%u}" HW_ERR, curr_seqno); + pr_info("%sHardware error from AEST %s\n", pfx_seq, event->node_name); + + switch (event->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + pr_err("%s Error from CPU%d\n", pfx_seq, event->id0); + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + pr_err("%s Error from memory at SRAT proximity domain %#x\n", + pfx_seq, event->id0); + break; + case ACPI_AEST_SMMU_ERROR_NODE: + pr_err("%s Error from SMMU IORT node %#x subcomponent %#x\n", + pfx_seq, event->id0, event->id1); + break; + case ACPI_AEST_VENDOR_ERROR_NODE: + pr_err("%s Error from vendor hid %8.8s uid %#x\n", pfx_seq, + event->hid, event->id1); + break; + case ACPI_AEST_GIC_ERROR_NODE: + pr_err("%s Error from GIC type %#x instance %#x\n", pfx_seq, + event->id0, event->id1); + break; + default: + pr_err("%s Unknown AEST node type\n", pfx_seq); + return; + } + + index = event->index; + regs = &event->regs; + + pr_err("%s ERR%dFR: 0x%llx\n", pfx_seq, index, regs->err_fr); + pr_err("%s ERR%dCTRL: 0x%llx\n", pfx_seq, index, regs->err_ctlr); + pr_err("%s ERR%dSTATUS: 0x%llx\n", pfx_seq, index, regs->err_status); + if (regs->err_status & ERR_STATUS_AV) + pr_err("%s ERR%dADDR: 0x%llx\n", pfx_seq, index, + regs->err_addr); + + if (regs->err_status & ERR_STATUS_MV) { + pr_err("%s ERR%dMISC0: 0x%llx\n", pfx_seq, index, + regs->err_misc[0]); + pr_err("%s ERR%dMISC1: 0x%llx\n", pfx_seq, index, + regs->err_misc[1]); + pr_err("%s ERR%dMISC2: 0x%llx\n", pfx_seq, index, + regs->err_misc[2]); + pr_err("%s ERR%dMISC3: 0x%llx\n", pfx_seq, index, + regs->err_misc[3]); + } +} + +static void aest_handle_memory_failure(u64 addr) +{ + unsigned long pfn; + + pfn = PHYS_PFN(addr); + + if (!pfn_valid(pfn)) { + pr_warn(HW_ERR "Invalid physical address: %#llx\n", addr); + return; + } + +#ifdef CONFIG_MEMORY_FAILURE + memory_failure(pfn, 0); +#endif +} + +static void init_aest_event(struct aest_event *event, + struct aest_record *record, + struct ras_ext_regs *regs) +{ + struct aest_node *node = record->node; + struct acpi_aest_node *info = node->info; + + event->type = node->type; + event->node_name = node->name; + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + if (info->processor->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) + event->id0 = smp_processor_id(); + else + event->id0 = get_cpu_for_acpi_id( + info->processor->processor_id); + + event->id1 = info->processor->resource_type; + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + event->id0 = info->memory->srat_proximity_domain; + break; + case ACPI_AEST_SMMU_ERROR_NODE: + event->id0 = info->smmu->iort_node_reference; + event->id1 = info->smmu->subcomponent_reference; + break; + case ACPI_AEST_VENDOR_ERROR_NODE: + event->id0 = 0; + event->id1 = info->vendor->acpi_uid; + event->hid = info->vendor->acpi_hid; + break; + case ACPI_AEST_GIC_ERROR_NODE: + event->id0 = info->gic->interface_type; + event->id1 = info->gic->instance_id; + break; + default: + event->id0 = 0; + event->id1 = 0; + } + + memcpy(&event->regs, regs, sizeof(*regs)); + event->index = record->index; + event->addressing_mode = record->addressing_mode; +} + +static int aest_node_gen_pool_add(struct aest_device *adev, + struct aest_record *record, + struct ras_ext_regs *regs) +{ + struct aest_event *event; + + if (!adev->pool) + return -EINVAL; + + event = (void *)gen_pool_alloc(adev->pool, sizeof(*event)); + if (!event) + return -ENOMEM; + + init_aest_event(event, record, regs); + llist_add(&event->llnode, &adev->event_list); + + return 0; +} + +static void aest_log(struct aest_record *record, struct ras_ext_regs *regs) +{ + struct aest_device *adev = record->node->adev; + + if (!aest_node_gen_pool_add(adev, record, regs)) + schedule_work(&adev->aest_work); +} + +void aest_register_decode_chain(struct notifier_block *nb) +{ + blocking_notifier_chain_register(&aest_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(aest_register_decode_chain); + +void aest_unregister_decode_chain(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&aest_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(aest_unregister_decode_chain); + +static void aest_node_pool_process(struct work_struct *work) +{ + struct llist_node *head; + struct aest_event *event; + struct aest_device *adev = + container_of(work, struct aest_device, aest_work); + u64 status, addr; + + head = llist_del_all(&adev->event_list); + if (!head) + return; + + head = llist_reverse_order(head); + llist_for_each_entry(event, head, llnode) { + aest_print(event); + + status = event->regs.err_status; + if (!(event->regs.err_addr & ERR_ADDR_AI) && + (status & (ERR_STATUS_UE | ERR_STATUS_DE))) { + if (event->addressing_mode == AEST_ADDREESS_SPA) + addr = event->regs.err_addr & PHYS_MASK; + aest_handle_memory_failure(addr); + } + + blocking_notifier_call_chain(&aest_decoder_chain, 0, event); + gen_pool_free(adev->pool, (unsigned long)event, sizeof(*event)); + } +} + +static int aest_node_pool_init(struct aest_device *adev) +{ + unsigned long addr, size; + + size = ilog2(sizeof(struct aest_event)); + adev->pool = + devm_gen_pool_create(adev->dev, size, -1, dev_name(adev->dev)); + if (!adev->pool) + return -ENOMEM; + + size = PAGE_ALIGN(size * AEST_NODE_ALLOCED_MAX); + addr = (unsigned long)devm_kzalloc(adev->dev, size, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + return gen_pool_add(adev->pool, addr, size, -1); +} + +static void aest_panic(struct aest_record *record, struct ras_ext_regs *regs, + char *msg) +{ + struct aest_event event = { 0 }; + + init_aest_event(&event, record, regs); + + aest_print(&event); + + panic(msg); +} + +static void aest_proc_record(struct aest_record *record, void *data) +{ + struct ras_ext_regs regs = { 0 }; + int *count = data; + u64 ue; + + regs.err_status = record_read(record, ERXSTATUS); + if (!(regs.err_status & ERR_STATUS_V)) + return; + + (*count)++; + + if (regs.err_status & ERR_STATUS_AV) + regs.err_addr = record_read(record, ERXADDR); + + regs.err_fr = record_read(record, ERXFR); + regs.err_ctlr = record_read(record, ERXCTLR); + + if (regs.err_status & ERR_STATUS_MV) { + regs.err_misc[0] = record_read(record, ERXMISC0); + regs.err_misc[1] = record_read(record, ERXMISC1); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + regs.err_misc[2] = record_read(record, ERXMISC2); + regs.err_misc[3] = record_read(record, ERXMISC3); + } + + if (record->node->info->interface_hdr->flags & + AEST_XFACE_FLAG_CLEAR_MISC) { + record_write(record, ERXMISC0, 0); + record_write(record, ERXMISC1, 0); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + record_write(record, ERXMISC2, 0); + record_write(record, ERXMISC3, 0); + } + /* ce count is 0 if record do not support ce */ + } else if (record->ce.count > 0) + record_write(record, ERXMISC0, record->ce.reg_val); + } + + /* panic if unrecoverable and uncontainable error encountered */ + ue = FIELD_GET(ERR_STATUS_UET, regs.err_status); + if ((regs.err_status & ERR_STATUS_UE) && + (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) + aest_panic(record, ®s, + "AEST: unrecoverable error encountered"); + + aest_log(record, ®s); + + /* Write-one-to-clear the bits we've seen */ + regs.err_status &= ERR_STATUS_W1TC; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_CE) + regs.err_status |= ERR_STATUS_CE; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_UET) + regs.err_status |= ERR_STATUS_UET; + + record_write(record, ERXSTATUS, regs.err_status); +} + +static void aest_node_foreach_record(void (*func)(struct aest_record *, void *), + struct aest_node *node, void *data, + unsigned long *bitmap) +{ + int i; + + for_each_clear_bit(i, bitmap, node->record_count) { + aest_select_record(node, i); + + func(&node->records[i], data); + + aest_sync(node); + } +} + +static int aest_proc(struct aest_node *node) +{ + int count = 0, i, j, size = node->record_count; + u64 err_group = 0; + + aest_node_dbg(node, "Poll bitmap %*pb\n", size, + node->record_implemented); + aest_node_foreach_record(aest_proc_record, node, &count, + node->record_implemented); + + if (!node->errgsr) + return count; + + aest_node_dbg(node, "Report bitmap %*pb\n", size, + node->status_reporting); + for (i = 0; i < BITS_TO_U64(size); i++) { + err_group = readq_relaxed((void *)node->errgsr + i * 8); + aest_node_dbg(node, "errgsr[%d]: 0x%llx\n", i, err_group); + + for_each_set_bit(j, (unsigned long *)&err_group, + BITS_PER_LONG) { + /* + * Error group base is only valid in Memory Map node, + * so driver do not need to write select register and + * sync. + */ + if (test_bit(i * BITS_PER_LONG + j, + node->status_reporting)) + continue; + aest_proc_record(&node->records[j], &count); + } + } + + return count; +} + +static irqreturn_t aest_irq_func(int irq, void *input) +{ + struct aest_device *adev = input; + int i; + + for (i = 0; i < adev->node_cnt; i++) + aest_proc(&adev->nodes[i]); + + return IRQ_HANDLED; +} + +static int aest_register_irq(struct aest_device *adev) +{ + int i, irq, ret; + char *irq_desc; + + irq_desc = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%s.", + dev_driver_string(adev->dev), + dev_name(adev->dev)); + if (!irq_desc) + return -ENOMEM; + + for (i = 0; i < MAX_GSI_PER_NODE; i++) { + irq = adev->irq[i]; + + if (!irq) + continue; + + if (irq_is_percpu_devid(irq)) { + ret = request_percpu_irq(irq, aest_irq_func, irq_desc, + adev->adev_oncore); + if (ret) + goto free; + } else { + ret = devm_request_irq(adev->dev, irq, aest_irq_func, 0, + irq_desc, adev); + if (ret) + return ret; + } + } + return 0; + +free: + for (; i >= 0; i--) { + irq = adev->irq[i]; + + if (irq_is_percpu_devid(irq)) + free_percpu_irq(irq, adev->adev_oncore); + } + + return ret; +} + +static void aest_enable_irq(struct aest_record *record) +{ + u64 err_ctlr; + struct aest_device *adev = record->node->adev; + + err_ctlr = record_read(record, ERXCTLR); + + if (adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]) + err_ctlr |= (ERR_CTLR_FI | ERR_CTLR_CFI); + if (adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]) + err_ctlr |= ERR_CTLR_UI; + + record_write(record, ERXCTLR, err_ctlr); +} + +static void aest_config_irq(struct aest_node *node) +{ + int i; + struct acpi_aest_node_interrupt_v2 *interrupt; + + if (!node->irq_config) + return; + + for (i = 0; i < node->info->interrupt_count; i++) { + interrupt = &node->info->interrupt[i]; + + if (interrupt->type == ACPI_AEST_NODE_FAULT_HANDLING) + writeq_relaxed(interrupt->gsiv, node->irq_config); + + if (interrupt->type == ACPI_AEST_NODE_ERROR_RECOVERY) + writeq_relaxed(interrupt->gsiv, node->irq_config + 8); + + aest_node_dbg(node, "config irq type %d gsiv %d at %llx", + interrupt->type, interrupt->gsiv, + (u64)node->irq_config); + } +} + static enum ras_ce_threshold aest_get_ce_threshold(struct aest_record *record) { u64 err_fr, err_fr_cec, err_fr_rp = -1; @@ -128,6 +564,7 @@ static int aest_init_record(struct aest_record *record, int i, record->index = i; record->node = node; aest_set_ce_threshold(record); + aest_enable_irq(record); aest_record_dbg(record, "base: %p, index: %d, address mode: %x\n", record->regs_base, record->index, @@ -232,6 +669,21 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, } } + address = node->info->common->interrupt_config_register_base; + if ((flags & AEST_XFACE_FLAG_INT_CONFIG) && address) { + if (address - anode->interface_hdr->address < node->group->size) + node->irq_config = + node->base + + (address - anode->interface_hdr->address); + else { + node->irq_config = + devm_ioremap(adev->dev, address, PAGE_SIZE); + if (!node->irq_config) + return -ENOMEM; + } + } + aest_config_irq(node); + ret = aest_node_set_errgsr(adev, node); if (ret) return ret; @@ -276,6 +728,66 @@ static int aest_init_nodes(struct aest_device *adev, struct aest_hnode *ahnode) return 0; } +static int __setup_ppi(struct aest_device *adev) +{ + int cpu, i; + struct aest_device *oncore_adev; + struct aest_node *oncore_node; + size_t size; + + adev->adev_oncore = &percpu_adev; + for_each_possible_cpu(cpu) { + oncore_adev = per_cpu_ptr(&percpu_adev, cpu); + memcpy(oncore_adev, adev, sizeof(struct aest_device)); + + oncore_adev->nodes = + devm_kcalloc(adev->dev, oncore_adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!oncore_adev->nodes) + return -ENOMEM; + + size = adev->node_cnt * sizeof(struct aest_node); + memcpy(oncore_adev->nodes, adev->nodes, size); + for (i = 0; i < oncore_adev->node_cnt; i++) { + oncore_node = &oncore_adev->nodes[i]; + oncore_node->records = devm_kcalloc( + adev->dev, oncore_node->record_count, + sizeof(struct aest_record), GFP_KERNEL); + if (!oncore_node->records) + return -ENOMEM; + + size = oncore_node->record_count * + sizeof(struct aest_record); + memcpy(oncore_node->records, adev->nodes[i].records, + size); + } + + aest_dev_dbg(adev, "Init device on CPU%d.\n", cpu); + } + + return 0; +} + +static int aest_setup_irq(struct platform_device *pdev, + struct aest_device *adev) +{ + int fhi_irq, eri_irq; + + fhi_irq = platform_get_irq_byname_optional(pdev, AEST_FHI_NAME); + if (fhi_irq > 0) + adev->irq[0] = fhi_irq; + + eri_irq = platform_get_irq_byname_optional(pdev, AEST_ERI_NAME); + if (eri_irq > 0) + adev->irq[1] = eri_irq; + + /* Allocate and initialise the percpu device pointer for PPI */ + if (irq_is_percpu(fhi_irq) || irq_is_percpu(eri_irq)) + return __setup_ppi(adev); + + return 0; +} + static int aest_device_probe(struct platform_device *pdev) { int ret; @@ -289,14 +801,31 @@ static int aest_device_probe(struct platform_device *pdev) adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); if (!adev) return -ENOMEM; - adev->dev = &pdev->dev; adev->id = pdev->id; aest_set_name(adev, ahnode); + + INIT_WORK(&adev->aest_work, aest_node_pool_process); + ret = aest_node_pool_init(adev); + if (ret) { + aest_dev_err(adev, "Failed init aest node pool.\n"); + return ret; + } + init_llist_head(&adev->event_list); + ret = aest_init_nodes(adev, ahnode); if (ret) return ret; + ret = aest_setup_irq(pdev, adev); + if (ret) + return ret; + + ret = aest_register_irq(adev); + if (ret) { + aest_dev_err(adev, "register irq failed\n"); + return ret; + } platform_set_drvdata(pdev, adev); aest_dev_dbg(adev, "Node cnt: %x, id: %x\n", adev->node_cnt, adev->id); diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 85eeed79bcbee..a5e43b2a2e906 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -67,6 +67,34 @@ #define GIC_ERRDEVARCH 0xFFBC +struct aest_event { + struct llist_node llnode; + char *node_name; + u32 type; + /* + * Different nodes have different meanings: + * - Processor node : processor number. + * - Memory node : SRAT proximity domain. + * - SMMU node : IORT proximity domain. + * - GIC node : interface type. + */ + u32 id0; + /* + * Different nodes have different meanings: + * - Processor node : processor resource type. + * - Memory node : Non. + * - SMMU node : subcomponent reference. + * - Vendor node : Unique ID. + * - GIC node : instance identifier. + */ + u32 id1; + /* Vendor node : hardware ID. */ + char *hid; + u32 index; + int addressing_mode; + struct ras_ext_regs regs; +}; + struct aest_access { u64 (*read)(void *base, u32 offset); void (*write)(void *base, u32 offset, u64 val); @@ -141,6 +169,7 @@ struct aest_node { void *errgsr; void *base; void *inj; + void *irq_config; /* * This bitmap indicates which of the error records within this error @@ -172,6 +201,7 @@ struct aest_node { int record_count; struct aest_record *records; + struct aest_node __percpu *oncore_node; }; struct aest_device { @@ -180,6 +210,12 @@ struct aest_device { int node_cnt; struct aest_node *nodes; u32 id; + int irq[MAX_GSI_PER_NODE]; + + struct work_struct aest_work; + struct gen_pool *pool; + struct llist_head event_list; + struct aest_device __percpu *adev_oncore; }; static const char *const aest_node_name[] = { @@ -283,3 +319,23 @@ static const struct aest_access aest_access[] = { }, { } }; + +/* + * Each PE may has multi error record, you must selects an error + * record to be accessed through the Error Record System + * registers. + */ +static inline void aest_select_record(struct aest_node *node, int index) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) { + write_sysreg_s(index, SYS_ERRSELR_EL1); + isb(); + } +} + +/* Ensure all writes has taken effect. */ +static inline void aest_sync(struct aest_node *node) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) + isb(); +} diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index a7898c643896e..3a899f57f92fb 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -10,6 +10,13 @@ #define AEST_FHI_NAME "AEST:FHI" #define AEST_ERI_NAME "AEST:ERI" +/* AEST component */ +#define ACPI_AEST_PROC_FLAG_GLOBAL (1<<0) +#define ACPI_AEST_PROC_FLAG_SHARED (1<<1) + +#define AEST_ADDREESS_SPA 0 +#define AEST_ADDREESS_LA 1 + /* AEST interrupt */ #define AEST_INTERRUPT_MODE BIT(0) diff --git a/include/linux/ras.h b/include/linux/ras.h index 468941bfe855f..05096f049dacb 100644 --- a/include/linux/ras.h +++ b/include/linux/ras.h @@ -63,4 +63,12 @@ amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; } #define GET_LOGICAL_INDEX(mpidr) -EINVAL #endif /* CONFIG_ARM || CONFIG_ARM64 */ +#if IS_ENABLED(CONFIG_AEST) +void aest_register_decode_chain(struct notifier_block *nb); +void aest_unregister_decode_chain(struct notifier_block *nb); +#else +static inline void aest_register_decode_chain(struct notifier_block *nb) {} +static inline void aest_unregister_decode_chain(struct notifier_block *nb) {} +#endif /* CONFIG_AEST */ + #endif /* __RAS_H__ */ From f81d1766487699e69ebd3a867a29fdcd33ca977c Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:49 +0800 Subject: [PATCH 0360/1058] FROMLIST: ras: AEST: Add cpuhp callback Move the configuration of interrupts and CE thresholds into the CPU hotplug callbacks for the per-CPU AEST node. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-10-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 118 ++++++++++++++++++++++++++++++++++- drivers/ras/aest/aest.h | 5 ++ include/linux/cpuhotplug.h | 1 + 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 5ec0ba38f51b4..686dde6f2e680 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -5,6 +5,7 @@ * Copyright (c) 2025, Alibaba Group. */ +#include #include #include #include @@ -563,8 +564,6 @@ static int aest_init_record(struct aest_record *record, int i, record->addressing_mode = test_bit(i, node->info->addressing_mode); record->index = i; record->node = node; - aest_set_ce_threshold(record); - aest_enable_irq(record); aest_record_dbg(record, "base: %p, index: %d, address mode: %x\n", record->regs_base, record->index, @@ -572,9 +571,113 @@ static int aest_init_record(struct aest_record *record, int i, return 0; } +static void aest_online_record(struct aest_record *record, void *data) +{ + if (record_read(record, ERXFR) & ERR_FR_CE) + aest_set_ce_threshold(record); + + aest_enable_irq(record); +} + +static void aest_online_oncore_node(struct aest_node *node) +{ + int count; + + count = aest_proc(node); + aest_node_dbg(node, "Find %d error on CPU%d before AEST probe\n", count, + smp_processor_id()); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->record_implemented); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->status_reporting); +} + +static void aest_online_oncore_dev(void *data) +{ + int fhi_irq, eri_irq, i; + struct aest_device *adev = this_cpu_ptr(data); + + for (i = 0; i < adev->node_cnt; i++) + aest_online_oncore_node(&adev->nodes[i]); + + fhi_irq = adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + enable_percpu_irq(fhi_irq, IRQ_TYPE_NONE); + eri_irq = adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + enable_percpu_irq(eri_irq, IRQ_TYPE_NONE); +} + +static void aest_offline_oncore_dev(void *data) +{ + int fhi_irq, eri_irq; + struct aest_device *adev = this_cpu_ptr(data); + + fhi_irq = adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + disable_percpu_irq(fhi_irq); + eri_irq = adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + disable_percpu_irq(eri_irq); +} + +static void aest_online_dev(struct aest_device *adev) +{ + int count, i; + struct aest_node *node; + + for (i = 0; i < adev->node_cnt; i++) { + node = &adev->nodes[i]; + + if (!node->name) + continue; + + count = aest_proc(node); + aest_node_dbg(node, "Find %d error before AEST probe\n", count); + + aest_config_irq(node); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->record_implemented); + aest_node_foreach_record(aest_online_record, node, NULL, + node->status_reporting); + } +} + +static int aest_starting_cpu(unsigned int cpu) +{ + pr_debug("CPU%d starting\n", cpu); + aest_online_oncore_dev(&percpu_adev); + + return 0; +} + +static int aest_dying_cpu(unsigned int cpu) +{ + pr_debug("CPU%d dying\n", cpu); + aest_offline_oncore_dev(&percpu_adev); + + return 0; +} + static void aest_device_remove(struct platform_device *pdev) { + struct aest_device *adev = platform_get_drvdata(pdev); + int i; + platform_set_drvdata(pdev, NULL); + + if (adev->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return; + + on_each_cpu(aest_offline_oncore_dev, adev->adev_oncore, 1); + + for (i = 0; i < MAX_GSI_PER_NODE; i++) { + if (adev->irq[i]) + free_percpu_irq(adev->irq[i], adev->adev_oncore); + } } static char *alloc_aest_node_name(struct aest_node *node) @@ -682,7 +785,6 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, return -ENOMEM; } } - aest_config_irq(node); ret = aest_node_set_errgsr(adev, node); if (ret) @@ -826,6 +928,16 @@ static int aest_device_probe(struct platform_device *pdev) aest_dev_err(adev, "register irq failed\n"); return ret; } + + if (aest_dev_is_oncore(adev)) + ret = cpuhp_setup_state(CPUHP_AP_ARM_AEST_STARTING, + "drivers/acpi/arm64/aest:starting", + aest_starting_cpu, aest_dying_cpu); + else + aest_online_dev(adev); + if (ret) + return ret; + platform_set_drvdata(pdev, adev); aest_dev_dbg(adev, "Node cnt: %x, id: %x\n", adev->node_cnt, adev->id); diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index a5e43b2a2e906..f85e81ff35a6e 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -339,3 +339,8 @@ static inline void aest_sync(struct aest_node *node) if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) isb(); } + +static inline bool aest_dev_is_oncore(struct aest_device *adev) +{ + return adev->type == ACPI_AEST_PROCESSOR_ERROR_NODE; +} diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 0fb3a2a62eb00..7f20b820bad11 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -178,6 +178,7 @@ enum cpuhp_state { CPUHP_AP_HYPERV_TIMER_STARTING, /* Must be the last timer callback */ CPUHP_AP_DUMMY_TIMER_STARTING, + CPUHP_AP_ARM_AEST_STARTING, CPUHP_AP_ARM_XEN_STARTING, CPUHP_AP_ARM_XEN_RUNSTATE_STARTING, CPUHP_AP_ARM_CORESIGHT_CTI_STARTING, From 12cd839286898861586fccb5c4694aac1e1b8ee5 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:50 +0800 Subject: [PATCH 0361/1058] FROMLIST: ras: AEST: Introduce AEST driver sysfs interface Exposes certain AEST driver information to userspace. Only ROOT can access these interface because it includes hardware-sensitive information: ls /sys/kernel/debug/aest/ memory smmu ... ls /sys/kernel/debug/aest/memory/ record0 record1 ... All details at: Documentation/ABI/testing/debugfs-aest Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-11-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- Documentation/ABI/testing/debugfs-aest | 32 +++++++ MAINTAINERS | 1 + drivers/ras/aest/Makefile | 1 + drivers/ras/aest/aest-core.c | 13 +++ drivers/ras/aest/aest-sysfs.c | 118 +++++++++++++++++++++++++ drivers/ras/aest/aest.h | 8 ++ 6 files changed, 173 insertions(+) create mode 100644 Documentation/ABI/testing/debugfs-aest create mode 100644 drivers/ras/aest/aest-sysfs.c diff --git a/Documentation/ABI/testing/debugfs-aest b/Documentation/ABI/testing/debugfs-aest new file mode 100644 index 0000000000000..8bacc6bb20b6d --- /dev/null +++ b/Documentation/ABI/testing/debugfs-aest @@ -0,0 +1,32 @@ +What: /sys/kernel/debug/aest/./ +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + Directory represented a AEST device, means device type, + like: + + - processor + - memory + - smmu + - ... + + is the unique ID for this device. + +What: /sys/kernel/debug/aest/.//* +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + Attibute for aest node which belong this device, the format + of node name is: - + + See more at: + https://developer.arm.com/documentation/den0085/latest/ + +What: /sys/kernel/debug/aest/.//record/err_* +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RO) Read err_* register and return val. diff --git a/MAINTAINERS b/MAINTAINERS index 6139e5257c2b8..5d285cdd60d0c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -345,6 +345,7 @@ M: Ruidong Tian L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org S: Supported +F: Documentation/ABI/testing/debugfs-aest F: arch/arm64/include/asm/ras.h F: drivers/acpi/arm64/aest.c F: drivers/ras/aest/ diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile index a6ba7e36fb432..75495413d2b6e 100644 --- a/drivers/ras/aest/Makefile +++ b/drivers/ras/aest/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_AEST) += aest.o aest-y := aest-core.o +aest-y += aest-sysfs.o diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 686dde6f2e680..3bcc635cf8e4d 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -20,6 +20,9 @@ DEFINE_PER_CPU(struct aest_device, percpu_adev); #undef pr_fmt #define pr_fmt(fmt) "AEST: " fmt +#ifdef CONFIG_DEBUG_FS +struct dentry *aest_debugfs; +#endif /* * This memory pool is only to be used to save AEST node in AEST irq context. * There can be 500 AEST node at most. @@ -940,6 +943,8 @@ static int aest_device_probe(struct platform_device *pdev) platform_set_drvdata(pdev, adev); + aest_dev_init_debugfs(adev); + aest_dev_dbg(adev, "Node cnt: %x, id: %x\n", adev->node_cnt, adev->id); return 0; @@ -955,12 +960,20 @@ static struct platform_driver aest_driver = { static int __init aest_init(void) { +#ifdef CONFIG_DEBUG_FS + aest_debugfs = debugfs_create_dir("aest", NULL); +#endif + return platform_driver_register(&aest_driver); } module_init(aest_init); static void __exit aest_exit(void) { +#ifdef CONFIG_DEBUG_FS + debugfs_remove(aest_debugfs); +#endif + platform_driver_unregister(&aest_driver); } module_exit(aest_exit); diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c new file mode 100644 index 0000000000000..f3b5427ff4f0f --- /dev/null +++ b/drivers/ras/aest/aest-sysfs.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include "aest.h" + +/******************************************************************************* + * + * Attribute for AEST record + * + ******************************************************************************/ + +#define DEFINE_AEST_DEBUGFS_ATTR(name, offset) \ +static int name##_get(void *data, u64 *val) \ +{ \ + struct aest_record *record = data; \ + *val = record_read(record, offset); \ + return 0; \ +} \ +static int name##_set(void *data, u64 val) \ +{ \ + struct aest_record *record = data; \ + record_write(record, offset, val); \ + return 0; \ +} \ +DEFINE_DEBUGFS_ATTRIBUTE(name##_ops, name##_get, name##_set, "%#llx\n") + +DEFINE_AEST_DEBUGFS_ATTR(err_fr, ERXFR); +DEFINE_AEST_DEBUGFS_ATTR(err_ctrl, ERXCTLR); +DEFINE_AEST_DEBUGFS_ATTR(err_status, ERXSTATUS); +DEFINE_AEST_DEBUGFS_ATTR(err_addr, ERXADDR); +DEFINE_AEST_DEBUGFS_ATTR(err_misc0, ERXMISC0); +DEFINE_AEST_DEBUGFS_ATTR(err_misc1, ERXMISC1); +DEFINE_AEST_DEBUGFS_ATTR(err_misc2, ERXMISC2); +DEFINE_AEST_DEBUGFS_ATTR(err_misc3, ERXMISC3); + +static void aest_record_init_debugfs(struct aest_record *record) +{ + debugfs_create_file("err_fr", 0600, record->debugfs, record, + &err_fr_ops); + debugfs_create_file("err_ctrl", 0600, record->debugfs, record, + &err_ctrl_ops); + debugfs_create_file("err_status", 0600, record->debugfs, record, + &err_status_ops); + debugfs_create_file("err_addr", 0600, record->debugfs, record, + &err_addr_ops); + debugfs_create_file("err_misc0", 0600, record->debugfs, record, + &err_misc0_ops); + debugfs_create_file("err_misc1", 0600, record->debugfs, record, + &err_misc1_ops); + debugfs_create_file("err_misc2", 0600, record->debugfs, record, + &err_misc2_ops); + debugfs_create_file("err_misc3", 0600, record->debugfs, record, + &err_misc3_ops); +} + +static void +aest_node_init_debugfs(struct aest_node *node) +{ + int i; + struct aest_record *record; + + for (i = 0; i < node->record_count; i++) { + record = &node->records[i]; + if (!record->name) + continue; + record->debugfs = debugfs_create_dir(record->name, + node->debugfs); + aest_record_init_debugfs(record); + } +} + +static void +aest_oncore_dev_init_debugfs(struct aest_device *adev) +{ + int cpu, i; + struct aest_node *node; + struct aest_device *percpu_dev; + char name[16]; + + for_each_possible_cpu(cpu) { + percpu_dev = this_cpu_ptr(adev->adev_oncore); + + snprintf(name, sizeof(name), "processor%u", cpu); + percpu_dev->debugfs = debugfs_create_dir(name, aest_debugfs); + + for (i = 0; i < adev->node_cnt; i++) { + node = &adev->nodes[i]; + + node->debugfs = debugfs_create_dir(node->name, + percpu_dev->debugfs); + aest_node_init_debugfs(node); + } + } +} + +void aest_dev_init_debugfs(struct aest_device *adev) +{ + int i; + struct aest_node *node; + + adev->debugfs = debugfs_create_dir(dev_name(adev->dev), aest_debugfs); + if (aest_dev_is_oncore(adev)) { + aest_oncore_dev_init_debugfs(adev); + return; + } + + for (i = 0; i < adev->node_cnt; i++) { + node = &adev->nodes[i]; + if (!node->name) + continue; + node->debugfs = debugfs_create_dir(node->name, adev->debugfs); + aest_node_init_debugfs(node); + } +} diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index f85e81ff35a6e..ceb9e32bcee3c 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -7,6 +7,7 @@ #include #include +#include #define MAX_GSI_PER_NODE 2 #define DEFAULT_CE_THRESHOLD 1 @@ -67,6 +68,8 @@ #define GIC_ERRDEVARCH 0xFFBC +extern struct dentry *aest_debugfs; + struct aest_event { struct llist_node llnode; char *node_name; @@ -133,6 +136,7 @@ struct aest_record { struct ce_threshold ce; enum ras_ce_threshold threshold_type; + struct dentry *debugfs; }; struct aest_group { @@ -201,6 +205,7 @@ struct aest_node { int record_count; struct aest_record *records; + struct dentry *debugfs; struct aest_node __percpu *oncore_node; }; @@ -215,6 +220,7 @@ struct aest_device { struct work_struct aest_work; struct gen_pool *pool; struct llist_head event_list; + struct dentry *debugfs; struct aest_device __percpu *adev_oncore; }; @@ -344,3 +350,5 @@ static inline bool aest_dev_is_oncore(struct aest_device *adev) { return adev->type == ACPI_AEST_PROCESSOR_ERROR_NODE; } + +void aest_dev_init_debugfs(struct aest_device *adev); From 3261cd1ec4a2964f3fd56ce9875e870cc02cf5c0 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:51 +0800 Subject: [PATCH 0362/1058] FROMLIST: ras: AEST: Add error count tracking and debugfs interface This commit introduces error counting functionality for AEST records. Previously, error statistics were not directly available for individual error records or AEST nodes. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-12-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- Documentation/ABI/testing/debugfs-aest | 14 ++++++ drivers/ras/aest/aest-core.c | 21 +++++++++ drivers/ras/aest/aest-sysfs.c | 64 ++++++++++++++++++++++++++ drivers/ras/aest/aest.h | 10 ++++ 4 files changed, 109 insertions(+) diff --git a/Documentation/ABI/testing/debugfs-aest b/Documentation/ABI/testing/debugfs-aest index 8bacc6bb20b6d..295df9e9b4558 100644 --- a/Documentation/ABI/testing/debugfs-aest +++ b/Documentation/ABI/testing/debugfs-aest @@ -24,9 +24,23 @@ Description: See more at: https://developer.arm.com/documentation/den0085/latest/ +What: /sys/kernel/debug/aest/.//err_count +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for all error records of this node. + What: /sys/kernel/debug/aest/.//record/err_* Date: Dec 2025 KernelVersion: 6.19 Contact: Ruidong Tian Description: (RO) Read err_* register and return val. + +What: /sys/kernel/debug/aest/.//record/err_count +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for all this records. diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 3bcc635cf8e4d..75cca98024ad7 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -170,6 +170,27 @@ static int aest_node_gen_pool_add(struct aest_device *adev, init_aest_event(event, record, regs); llist_add(&event->llnode, &adev->event_list); + if (regs->err_status & ERR_STATUS_CE) + record->count.ce++; + if (regs->err_status & ERR_STATUS_DE) + record->count.de++; + if (regs->err_status & ERR_STATUS_UE) { + switch (regs->err_status & ERR_STATUS_UET) { + case ERR_STATUS_UET_UC: + record->count.uc++; + break; + case ERR_STATUS_UET_UEU: + record->count.ueu++; + break; + case ERR_STATUS_UET_UER: + record->count.uer++; + break; + case ERR_STATUS_UET_UEO: + record->count.ueo++; + break; + } + } + return 0; } diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c index f3b5427ff4f0f..b54e879506aa9 100644 --- a/drivers/ras/aest/aest-sysfs.c +++ b/drivers/ras/aest/aest-sysfs.c @@ -7,6 +7,46 @@ #include "aest.h" +static void +aest_error_count(struct aest_record *record, void *data) +{ + struct record_count *count = data; + + count->ce += record->count.ce; + count->de += record->count.de; + count->uc += record->count.uc; + count->ueu += record->count.ueu; + count->uer += record->count.uer; + count->ueo += record->count.ueo; +} + +/******************************************************************************* + * + * Debugfs for AEST node + * + ******************************************************************************/ + +static int aest_node_err_count_show(struct seq_file *m, void *data) +{ + struct aest_node *node = m->private; + struct record_count count = { 0 }; + int i; + + for (i = 0; i < node->record_count; i++) + aest_error_count(&node->records[i], &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(aest_node_err_count); + /******************************************************************************* * * Attribute for AEST record @@ -37,6 +77,25 @@ DEFINE_AEST_DEBUGFS_ATTR(err_misc1, ERXMISC1); DEFINE_AEST_DEBUGFS_ATTR(err_misc2, ERXMISC2); DEFINE_AEST_DEBUGFS_ATTR(err_misc3, ERXMISC3); +static int aest_record_err_count_show(struct seq_file *m, void *data) +{ + struct aest_record *record = m->private; + struct record_count count = { 0 }; + + aest_error_count(record, &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(aest_record_err_count); + static void aest_record_init_debugfs(struct aest_record *record) { debugfs_create_file("err_fr", 0600, record->debugfs, record, @@ -55,6 +114,8 @@ static void aest_record_init_debugfs(struct aest_record *record) &err_misc2_ops); debugfs_create_file("err_misc3", 0600, record->debugfs, record, &err_misc3_ops); + debugfs_create_file("err_count", 0400, record->debugfs, record, + &aest_record_err_count_fops); } static void @@ -63,6 +124,9 @@ aest_node_init_debugfs(struct aest_node *node) int i; struct aest_record *record; + debugfs_create_file("err_count", 0400, node->debugfs, node, + &aest_node_err_count_fops); + for (i = 0; i < node->record_count; i++) { record = &node->records[i]; if (!record->name) diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index ceb9e32bcee3c..802430857dc49 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -116,6 +116,15 @@ struct ce_threshold { u64 reg_val; }; +struct record_count { + u64 ce; + u64 de; + u64 uc; + u64 uer; + u64 ueo; + u64 ueu; +}; + struct aest_record { char *name; int index; @@ -136,6 +145,7 @@ struct aest_record { struct ce_threshold ce; enum ras_ce_threshold threshold_type; + struct record_count count; struct dentry *debugfs; }; From 6c0e4efaae59948f4e257c03777b9ce1e7aed350 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:52 +0800 Subject: [PATCH 0363/1058] FROMLIST: ras: AEST: Allow configuring CE threshold via debugfs This commit introduces the ability to configure the Corrected Error (CE) threshold for AEST records through debugfs. This allows administrators to dynamically adjust the CE threshold for error reporting. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-13-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- Documentation/ABI/testing/debugfs-aest | 16 ++++++++++ drivers/ras/aest/aest-sysfs.c | 42 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Documentation/ABI/testing/debugfs-aest b/Documentation/ABI/testing/debugfs-aest index 295df9e9b4558..4d160072d37a7 100644 --- a/Documentation/ABI/testing/debugfs-aest +++ b/Documentation/ABI/testing/debugfs-aest @@ -24,6 +24,14 @@ Description: See more at: https://developer.arm.com/documentation/den0085/latest/ +What: /sys/kernel/debug/aest/.//ce_threshold +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) Write the ce threshold to all records of this node. Failed + if input exceeded the maximum threshold + What: /sys/kernel/debug/aest/.//err_count Date: Dec 2025 KernelVersion 6.19 @@ -38,6 +46,14 @@ Contact: Ruidong Tian Description: (RO) Read err_* register and return val. +What: /sys/kernel/debug/aest/.//record/ce_threshold +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RW) Read and write the ce threshold to this record. Failed + if input exceeded the maximum threshold + What: /sys/kernel/debug/aest/.//record/err_count Date: Dec 2025 KernelVersion 6.19 diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c index b54e879506aa9..392e7ad8328ed 100644 --- a/drivers/ras/aest/aest-sysfs.c +++ b/drivers/ras/aest/aest-sysfs.c @@ -7,6 +7,25 @@ #include "aest.h" +static void +aest_store_threshold(struct aest_record *record, void *data) +{ + u64 err_misc0, *threshold = data; + struct ce_threshold *ce = &record->ce; + + if (*threshold > ce->info->max_count) + return; + + ce->threshold = *threshold; + ce->count = ce->info->max_count - ce->threshold + 1; + + err_misc0 = record_read(record, ERXMISC0); + ce->reg_val = (err_misc0 & ~ce->info->mask) | + (ce->count << ce->info->shift); + + record_write(record, ERXMISC0, ce->reg_val); +} + static void aest_error_count(struct aest_record *record, void *data) { @@ -77,6 +96,27 @@ DEFINE_AEST_DEBUGFS_ATTR(err_misc1, ERXMISC1); DEFINE_AEST_DEBUGFS_ATTR(err_misc2, ERXMISC2); DEFINE_AEST_DEBUGFS_ATTR(err_misc3, ERXMISC3); +static int record_ce_threshold_get(void *data, u64 *val) +{ + struct aest_record *record = data; + + *val = record->ce.threshold; + return 0; +} + +static int record_ce_threshold_set(void *data, u64 val) +{ + u64 threshold = val; + struct aest_record *record = data; + + aest_store_threshold(record, &threshold); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(record_ce_threshold_ops, record_ce_threshold_get, + record_ce_threshold_set, "%llu\n"); + static int aest_record_err_count_show(struct seq_file *m, void *data) { struct aest_record *record = m->private; @@ -116,6 +156,8 @@ static void aest_record_init_debugfs(struct aest_record *record) &err_misc3_ops); debugfs_create_file("err_count", 0400, record->debugfs, record, &aest_record_err_count_fops); + debugfs_create_file("ce_threshold", 0600, record->debugfs, record, + &record_ce_threshold_ops); } static void From bb752228fd7b2b4be565e6cd2d282ebffcaf170f Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:53 +0800 Subject: [PATCH 0364/1058] FROMLIST: ras: AEST: Introduce AEST inject interface to test AEST driver AEST offers both soft and hard injection. Soft injection simulates errors in software, providing flexibility to define the error register content. Hard injection, on the other hand, utilizes error injection registers to introduce hardware faults, strictly requiring values that adhere to their specifications. Read Documentation/ABI/testing/debugfs-aest to learn how to use them. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-14-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- Documentation/ABI/testing/debugfs-aest | 37 +++++++ drivers/ras/aest/Makefile | 1 + drivers/ras/aest/aest-core.c | 24 +++-- drivers/ras/aest/aest-inject.c | 131 +++++++++++++++++++++++++ drivers/ras/aest/aest-sysfs.c | 8 +- drivers/ras/aest/aest.h | 2 + 6 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 drivers/ras/aest/aest-inject.c diff --git a/Documentation/ABI/testing/debugfs-aest b/Documentation/ABI/testing/debugfs-aest index 4d160072d37a7..cc41ea7032c72 100644 --- a/Documentation/ABI/testing/debugfs-aest +++ b/Documentation/ABI/testing/debugfs-aest @@ -60,3 +60,40 @@ KernelVersion 6.19 Contact: Ruidong Tian Description: (RO) Outputs error statistics for all this records. + +What: /sys/kernel/debug/aest/.//record/inject/err_* +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RW) These registers are used to simulate soft injection errors + by holding error register values. You can write any values + to them. To trigger the injection, you need to write soft_inject + at last. The validity of the injected error depends on the + value written to err_status. + + Accepts values - any. + +What: /sys/kernel/debug/aest/.//record/inject/soft_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) Write any value to this file to trigger the error + injection. Make sure you have specified all necessary error + parameters, i.e. this write should be the last step when + injecting errors. + + Accepts values - any. + +What: /sys/kernel/debug/aest/.//record/inject/hard_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) If the AEST table provides error injection registers, + you can write to them via this interface. For instance, + values can be written to the ERXPFGCTL register. The post-injection + behavior is then determined by the hardware specification. + + Accepts values - any. diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile index 75495413d2b6e..5ee10fc8b2e9d 100644 --- a/drivers/ras/aest/Makefile +++ b/drivers/ras/aest/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_AEST) += aest.o aest-y := aest-core.o aest-y += aest-sysfs.o +aest-y += aest-inject.o diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 75cca98024ad7..a290b482bf8b7 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -273,7 +273,7 @@ static void aest_panic(struct aest_record *record, struct ras_ext_regs *regs, panic(msg); } -static void aest_proc_record(struct aest_record *record, void *data) +void aest_proc_record(struct aest_record *record, void *data, bool fake) { struct ras_ext_regs regs = { 0 }; int *count = data; @@ -315,9 +315,15 @@ static void aest_proc_record(struct aest_record *record, void *data) /* panic if unrecoverable and uncontainable error encountered */ ue = FIELD_GET(ERR_STATUS_UET, regs.err_status); if ((regs.err_status & ERR_STATUS_UE) && - (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) - aest_panic(record, ®s, - "AEST: unrecoverable error encountered"); + (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) { + if (fake) + aest_record_info( + record, + "Simulated error! Skip panic due to fault injection\n"); + else + aest_panic(record, ®s, + "AEST: unrecoverable error encountered"); + } aest_log(record, ®s); @@ -335,7 +341,8 @@ static void aest_proc_record(struct aest_record *record, void *data) record_write(record, ERXSTATUS, regs.err_status); } -static void aest_node_foreach_record(void (*func)(struct aest_record *, void *), +static void aest_node_foreach_record(void (*func)(struct aest_record *, void *, + bool), struct aest_node *node, void *data, unsigned long *bitmap) { @@ -344,7 +351,7 @@ static void aest_node_foreach_record(void (*func)(struct aest_record *, void *), for_each_clear_bit(i, bitmap, node->record_count) { aest_select_record(node, i); - func(&node->records[i], data); + func(&node->records[i], data, false); aest_sync(node); } @@ -379,7 +386,7 @@ static int aest_proc(struct aest_node *node) if (test_bit(i * BITS_PER_LONG + j, node->status_reporting)) continue; - aest_proc_record(&node->records[j], &count); + aest_proc_record(&node->records[j], &count, false); } } @@ -595,7 +602,8 @@ static int aest_init_record(struct aest_record *record, int i, return 0; } -static void aest_online_record(struct aest_record *record, void *data) +static void aest_online_record(struct aest_record *record, void *data, + bool __unused) { if (record_read(record, ERXFR) & ERR_FR_CE) aest_set_ce_threshold(record); diff --git a/drivers/ras/aest/aest-inject.c b/drivers/ras/aest/aest-inject.c new file mode 100644 index 0000000000000..fe6ccac8338e4 --- /dev/null +++ b/drivers/ras/aest/aest-inject.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2024, Alibaba Group. + */ + +#include "aest.h" + +static struct ras_ext_regs regs_inj; + +struct inj_attr { + struct attribute attr; + ssize_t (*show)(struct aest_node *n, struct inj_attr *a, char *b); + ssize_t (*store)(struct aest_node *n, struct inj_attr *a, const char *b, + size_t c); +}; + +struct aest_inject { + struct aest_node *node; + struct kobject kobj; +}; + +#define to_inj(k) container_of(k, struct aest_inject, kobj) +#define to_inj_attr(a) container_of(a, struct inj_attr, attr) + +static u64 aest_sysreg_read_inject(void *__unused, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void aest_sysreg_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static u64 aest_iomem_read_inject(void *base, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void aest_iomem_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static struct aest_access aest_access_inject[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = aest_sysreg_read_inject, + .write = aest_sysreg_write_inject, + }, + + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = aest_iomem_read_inject, + .write = aest_iomem_write_inject, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = aest_iomem_read_inject, + .write = aest_iomem_write_inject, + }, + { } +}; + +static int soft_inject_store(void *data, u64 val) +{ + int count = 0; + struct aest_record record_inj, *record = data; + struct aest_node node_inj, *node = record->node; + + memcpy(&node_inj, node, sizeof(*node)); + node_inj.name = "AEST-injection"; + + record_inj.access = &aest_access_inject[node->info->interface_hdr->type]; + record_inj.node = &node_inj; + record_inj.index = record->index; + + regs_inj.err_status |= ERR_STATUS_V; + + aest_proc_record(&record_inj, &count, true); + + if (count != 1) + return -EIO; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(soft_inject_ops, NULL, soft_inject_store, "%llu\n"); + +static int hard_inject_store(void *data, u64 val) +{ + struct aest_record *record = data; + struct aest_node *node = record->node; + + if (!node->inj) + return -EPERM; + + aest_select_record(node, record->index); + record_write(record, ERXPFGCTL, val); + record_write(record, ERXPFGCDN, 0x100); + aest_sync(node); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(hard_inject_ops, NULL, hard_inject_store, "%llu\n"); + +void aest_inject_init_debugfs(struct aest_record *record) +{ + struct dentry *inj; + + inj = debugfs_create_dir("inject", record->debugfs); + + debugfs_create_u64("err_fr", 0600, inj, ®s_inj.err_fr); + debugfs_create_u64("err_ctrl", 0600, inj, ®s_inj.err_ctlr); + debugfs_create_u64("err_status", 0600, inj, ®s_inj.err_status); + debugfs_create_u64("err_addr", 0600, inj, ®s_inj.err_addr); + debugfs_create_u64("err_misc0", 0600, inj, ®s_inj.err_misc[0]); + debugfs_create_u64("err_misc1", 0600, inj, ®s_inj.err_misc[1]); + debugfs_create_u64("err_misc2", 0600, inj, ®s_inj.err_misc[2]); + debugfs_create_u64("err_misc3", 0600, inj, ®s_inj.err_misc[3]); + debugfs_create_file("soft_inject", 0400, inj, record, &soft_inject_ops); + + if (record->node->inj) + debugfs_create_file("hard_inject", 0400, inj, record, &hard_inject_ops); +} diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c index 392e7ad8328ed..66e9c1103f996 100644 --- a/drivers/ras/aest/aest-sysfs.c +++ b/drivers/ras/aest/aest-sysfs.c @@ -158,6 +158,7 @@ static void aest_record_init_debugfs(struct aest_record *record) &aest_record_err_count_fops); debugfs_create_file("ce_threshold", 0600, record->debugfs, record, &record_ce_threshold_ops); + aest_inject_init_debugfs(record); } static void @@ -190,8 +191,8 @@ aest_oncore_dev_init_debugfs(struct aest_device *adev) for_each_possible_cpu(cpu) { percpu_dev = this_cpu_ptr(adev->adev_oncore); - snprintf(name, sizeof(name), "processor%u", cpu); - percpu_dev->debugfs = debugfs_create_dir(name, aest_debugfs); + snprintf(name, sizeof(name), "processor%u%u", cpu); + percpu_dev->debugfs = debugfs_create_dir(name, adev->debugfs); for (i = 0; i < adev->node_cnt; i++) { node = &adev->nodes[i]; @@ -208,6 +209,9 @@ void aest_dev_init_debugfs(struct aest_device *adev) int i; struct aest_node *node; + if (!aest_debugfs) + dev_err(adev->dev, "debugfs not enabled\n"); + adev->debugfs = debugfs_create_dir(dev_name(adev->dev), aest_debugfs); if (aest_dev_is_oncore(adev)) { aest_oncore_dev_init_debugfs(adev); diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 802430857dc49..2f6a7b9ca4efd 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -362,3 +362,5 @@ static inline bool aest_dev_is_oncore(struct aest_device *adev) } void aest_dev_init_debugfs(struct aest_device *adev); +void aest_inject_init_debugfs(struct aest_record *record); +void aest_proc_record(struct aest_record *record, void *data, bool fake); From 0592b6d00daa4bf2bf6e40590da8c8f499807ad1 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:54 +0800 Subject: [PATCH 0365/1058] FROMLIST: ras: AEST: Add framework to process AEST vendor node AEST table include vendor error node to support the component that do not implement standard Arm RAS architecture[1]. Each vendor node may have their own initialize and interrupt handle function. This patch supply a framework to process vendor error nodes, the vendor process function is binded with vendor HID. [1]: https://developer.arm.com/documentation/ddi0587/latest/ Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-15-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 28 +++++++++++++++++++++++++++- drivers/ras/aest/aest.h | 5 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index a290b482bf8b7..047c9a8cffe40 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -922,6 +922,29 @@ static int aest_setup_irq(struct platform_device *pdev, return 0; } +static struct aest_vendor_match vendor_match[] = { + { }, +}; + +static int +aest_vendor_probe(struct aest_device *adev, struct aest_hnode *ahnode) +{ + int i; + struct acpi_aest_node *anode; + + anode = list_first_entry(&ahnode->list, struct acpi_aest_node, list); + if (!anode) + return -ENODEV; + + aest_dev_dbg(adev, "Try to probe vendor node %s\n", anode->vendor->acpi_hid); + for (i = 0; i < ARRAY_SIZE(vendor_match); i++) { + if (!strncmp(vendor_match[i].hid, anode->vendor->acpi_hid, 8)) + return vendor_match[i].probe(adev, ahnode); + } + + return -ENODEV; +} + static int aest_device_probe(struct platform_device *pdev) { int ret; @@ -947,7 +970,10 @@ static int aest_device_probe(struct platform_device *pdev) } init_llist_head(&adev->event_list); - ret = aest_init_nodes(adev, ahnode); + if (ahnode->type == ACPI_AEST_VENDOR_ERROR_NODE) + ret = aest_vendor_probe(adev, ahnode); + else + ret = aest_init_nodes(adev, ahnode); if (ret) return ret; diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 2f6a7b9ca4efd..304c03839d31f 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -244,6 +244,11 @@ static const char *const aest_node_name[] = { [ACPI_AEST_PROXY_ERROR_NODE] = "proxy", }; +struct aest_vendor_match { + char hid[ACPI_ID_LEN]; + int (*probe)(struct aest_device *adev, struct aest_hnode *anode); +}; + static inline int aest_set_name(struct aest_device *adev, struct aest_hnode *ahnode) { From 5a547863f4bbfde5c2a00c179f2cc0a873f71bcb Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:55 +0800 Subject: [PATCH 0366/1058] FROMLIST: ras: AEST: support vendor node CMN700 The CMN (Coherent Mesh Network) architecture incorporates five distinct device types. Each device type is associated with an error group register set. The struct aest_cmn_700 models a single CMN instance, while struct aest_cmn_700_child represents an individual CMN device. CMN's error records utilize a memory-mapped single error record view [1]. Critically, one error record corresponds to one AEST node, implying that a single CMN instance can generate hundreds of AEST nodes. To manage this scale, this driver introduces a virtual AEST node, which represents an entire CMN device, such as an HNI or HNF. This allows an HNF AEST node, for instance, to leverage its errgsr register to pinpoint which specific error record has reported an error. During the AEST probe phase, the CMN AEST driver identifies the CMN node type using the cmn_node_info register. It then reorganizes all AEST nodes belonging to the same CMN node type into a cohesive CMN AEST node structure. To locate the relevant CMN register addresses, the CMN's presence in the DSDT is required, along with the CMN node offset specified in the AEST vendor specification data [1]. [1]: https://developer.arm.com/documentation/102308/latest/ Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-16-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- arch/arm64/include/asm/arm-cmn.h | 47 +++++ drivers/perf/arm-cmn.c | 37 +--- drivers/ras/aest/Makefile | 1 + drivers/ras/aest/aest-cmn.c | 330 +++++++++++++++++++++++++++++++ drivers/ras/aest/aest-core.c | 42 ++-- drivers/ras/aest/aest.h | 39 ++++ 6 files changed, 444 insertions(+), 52 deletions(-) create mode 100644 arch/arm64/include/asm/arm-cmn.h create mode 100644 drivers/ras/aest/aest-cmn.c diff --git a/arch/arm64/include/asm/arm-cmn.h b/arch/arm64/include/asm/arm-cmn.h new file mode 100644 index 0000000000000..1b9f506797944 --- /dev/null +++ b/arch/arm64/include/asm/arm-cmn.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2015 ARM Ltd. + */ +#ifndef __ASM_ARM_CMN_H +#define __ASM_ARM_CMN_H + +#include + +/* Common register stuff */ +#define CMN_NODE_INFO 0x0000 +#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0) +#define CMN_NI_NODE_ID GENMASK_ULL(31, 16) +#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) + +enum cmn_node_type { + CMN_TYPE_INVALID, + CMN_TYPE_DVM, + CMN_TYPE_CFG, + CMN_TYPE_DTC, + CMN_TYPE_HNI, + CMN_TYPE_HNF, + CMN_TYPE_XP, + CMN_TYPE_SBSX, + CMN_TYPE_MPAM_S, + CMN_TYPE_MPAM_NS, + CMN_TYPE_RNI, + CMN_TYPE_RND = 0xd, + CMN_TYPE_RNSAM = 0xf, + CMN_TYPE_MTSX, + CMN_TYPE_HNP, + CMN_TYPE_CXRA = 0x100, + CMN_TYPE_CXHA, + CMN_TYPE_CXLA, + CMN_TYPE_CCRA, + CMN_TYPE_CCHA, + CMN_TYPE_CCLA, + CMN_TYPE_CCLA_RNI, + CMN_TYPE_HNS = 0x200, + CMN_TYPE_HNS_MPAM_S, + CMN_TYPE_HNS_MPAM_NS, + CMN_TYPE_APB = 0x1000, + /* Not a real node type */ + CMN_TYPE_WP = 0x7770 +}; + +#endif /* __ASM_ARM_CMN_H */ diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 6e5cc4086a9e2..4cf5d86647651 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -2,6 +2,7 @@ // Copyright (C) 2016-2020 Arm Limited // ARM CMN/CI interconnect PMU driver +#include #include #include #include @@ -19,11 +20,6 @@ #include /* Common register stuff */ -#define CMN_NODE_INFO 0x0000 -#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0) -#define CMN_NI_NODE_ID GENMASK_ULL(31, 16) -#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) - #define CMN_CHILD_INFO 0x0080 #define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0) #define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16) @@ -243,37 +239,6 @@ enum cmn_revision { REV_CI700_R2P0, }; -enum cmn_node_type { - CMN_TYPE_INVALID, - CMN_TYPE_DVM, - CMN_TYPE_CFG, - CMN_TYPE_DTC, - CMN_TYPE_HNI, - CMN_TYPE_HNF, - CMN_TYPE_XP, - CMN_TYPE_SBSX, - CMN_TYPE_MPAM_S, - CMN_TYPE_MPAM_NS, - CMN_TYPE_RNI, - CMN_TYPE_RND = 0xd, - CMN_TYPE_RNSAM = 0xf, - CMN_TYPE_MTSX, - CMN_TYPE_HNP, - CMN_TYPE_CXRA = 0x100, - CMN_TYPE_CXHA, - CMN_TYPE_CXLA, - CMN_TYPE_CCRA, - CMN_TYPE_CCHA, - CMN_TYPE_CCLA, - CMN_TYPE_CCLA_RNI, - CMN_TYPE_HNS = 0x200, - CMN_TYPE_HNS_MPAM_S, - CMN_TYPE_HNS_MPAM_NS, - CMN_TYPE_APB = 0x1000, - /* Not a real node type */ - CMN_TYPE_WP = 0x7770 -}; - enum cmn_filter_select { SEL_NONE = -1, SEL_OCCUP1ID, diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile index 5ee10fc8b2e9d..e5a45fde6d362 100644 --- a/drivers/ras/aest/Makefile +++ b/drivers/ras/aest/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_AEST) += aest.o aest-y := aest-core.o aest-y += aest-sysfs.o aest-y += aest-inject.o +aest-y += aest-cmn.o diff --git a/drivers/ras/aest/aest-cmn.c b/drivers/ras/aest/aest-cmn.c new file mode 100644 index 0000000000000..ad82ed163a8c5 --- /dev/null +++ b/drivers/ras/aest/aest-cmn.c @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table CMN700 Support + * + * Copyright (c) 2025, Alibaba Inc + */ + +#include + +#include "aest.h" + +/* + * CMN include 5 device types, each device type has an error group register set + * which contains a set of error records. The struct aest_cmn_700 represents + * one CMN Instance, and the struct aest_cmn_700_child represent one CMN device. + * The error record of CMN use memory-mapped single error record view, so one + * record is correspond to one AEST node, it means there will be hundreds of + * AEST node of CMN. As described in chapters 2.6.3.4 of Arm ACPI Spec[1], we + * use vendor define data to recognize the device type of an AEST node. So AEST + * driver can enumerate all CMN AEST node to initialize struct aest_cmn_700 and + * aest_cmn_700_child with HID, UID and other CMN info described in AEST or CMN + * register. + * + * Each CMN Instance has their own error interrupt and the struct aest_cmn_700 + * is passed to interrupt context. OS check error group register set to locate + * record which report error. All procedure is similar with chapters 3.8 in + * Arm CMN Spec[2]. + * + * The CMN RAS architecture is showed as follow: + * + * +----+ + * -->|XP | ...... + * | +----+ + * | + * | +----+ ...... + * | |HNI | +----------------+ + * | +----+ ->|record/AEST node| + * | | +----------------+ + * +------------+ | +----+ | . + * |CMN Instance|--| |HNF |---| . + * +------------+ | +----+ | . + * | | +----------------+ + * | +----+ ->|record/AEST node| + * | |SBSX| +----------------+ + * | +----+ ...... + * | + * | +----+ + * -->|CCG | ...... + * +----+ + * + * [1]: https://developer.arm.com/documentation/den0093/latest + * [2]: https://developer.arm.com/documentation/102308/latest + */ + +#define CMN_RAS_DEV_NUM 6 +#define CMN700_ERRGSR_NUM 8 +#define CMN_MAX_UID 8 +#define CMN_ERRDEVARCH 0x3FB8 +#define CMN_ERRDEVARCH_REV GENMASK(19, 16) +#define CMN_ERRGSR_OFFSET 0x3000 + +struct cmn_vendor_data { + int node_type; + int node_id; + int logic_id; +}; + +struct cmn_config { + int errgsr_num; + int dev_num; + int ras_ver; + const int *node_id_map; + const char *const *node_name; + int (*errgsr_mapping)(int errgsr_bit); + u64 (*errgsr_offset)(u64 hnd_ofset, int node_idx); +}; + +static const char *const cmn700_node_name[] = { + [CMN_TYPE_HNI] = "HNI", [CMN_TYPE_HNF] = "HNF", + [CMN_TYPE_XP] = "XP", [CMN_TYPE_SBSX] = "SBSX", + [CMN_TYPE_CXRA] = "RND", [CMN_TYPE_MTSX] = "MTSX", +}; + +static const int cmn700_node_id_map[] = { + [CMN_TYPE_HNI] = 1, [CMN_TYPE_HNF] = 2, [CMN_TYPE_XP] = 0, + [CMN_TYPE_SBSX] = 3, [CMN_TYPE_CXRA] = 4, [CMN_TYPE_MTSX] = 5, +}; + +static u64 cmn_dev_array[CMN_MAX_UID]; +static struct cmn_config *cmn_config; + +static u64 cmn700_errgsr_offset(u64 hnd_offset, int node_idx) +{ + return hnd_offset + CMN_ERRGSR_OFFSET + + (node_idx * 2) * CMN700_ERRGSR_NUM * 8; +} + +static struct cmn_config cmn700_config = { + .errgsr_num = CMN700_ERRGSR_NUM, + .dev_num = CMN_RAS_DEV_NUM, + .ras_ver = 1, + .node_name = cmn700_node_name, + .node_id_map = cmn700_node_id_map, + .errgsr_mapping = cmn700_errgsr_mapping, + .errgsr_offset = cmn700_errgsr_offset, +}; + +static acpi_status aest_cmn_700_resource_ioremap(struct acpi_resource *res, + void *data) +{ + struct acpi_resource_address64 addr64; + u32 *uid = data; + acpi_status status; + + status = acpi_resource_to_address64(res, &addr64); + if (ACPI_FAILURE(status) || (addr64.resource_type != ACPI_MEMORY_RANGE)) + return AE_OK; + + cmn_dev_array[*uid] = (u64)ioremap(addr64.address.minimum, + addr64.address.address_length); + + pr_debug("CMN device resource [%llx-%llx] ioremap to %llx\n", + addr64.address.minimum, addr64.address.maximum, + cmn_dev_array[*uid]); + + return AE_CTRL_TERMINATE; +} + +static acpi_status aest_cmn_get_dev_by_uid(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + u32 *match_uid = data; + acpi_status status; + unsigned long long uid; + + status = acpi_evaluate_integer(handle, METHOD_NAME__UID, NULL, &uid); + if (ACPI_FAILURE(status)) { + pr_err("Do not find devive\n"); + return_ACPI_STATUS(status); + } + + if (uid != *match_uid) + return AE_OK; + + pr_debug("CMN device instance %llx, walk through resource\n", uid); + + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + aest_cmn_700_resource_ioremap, data); + + if (ACPI_FAILURE(status)) { + pr_err("Device do not have resource\n"); + return_ACPI_STATUS(status); + } + + return AE_CTRL_TERMINATE; +} + +static inline int aest_cmn_node_ver(void *base) +{ + return FIELD_GET(CMN_ERRDEVARCH_REV, + readl_relaxed(base + CMN_ERRDEVARCH)); +} + +static int aest_cmn_init_node(struct aest_device *adev, + struct aest_node *cmn_node, + struct acpi_aest_node *anode, u64 type, + u64 errgsr_addr) +{ + cmn_node->info = anode; + cmn_node->name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s", + cmn_config->node_name[type]); + if (!cmn_node->name) + return -ENOMEM; + cmn_node->errgsr = (void *)errgsr_addr; + cmn_node->type = anode->type; + cmn_node->adev = adev; + cmn_node->version = cmn_config->ras_ver; + cmn_node->errgsr_num = cmn_config->errgsr_num; + cmn_node->errgsr_mapping = cmn_config->errgsr_mapping; + cmn_node->record_count = cmn_node->errgsr_num * BITS_PER_LONG / 2; + cmn_node->record_implemented = devm_bitmap_zalloc( + adev->dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->record_implemented) + return -ENOMEM; + bitmap_set(cmn_node->record_implemented, 0, cmn_node->record_count); + + cmn_node->status_reporting = devm_bitmap_zalloc( + adev->dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->status_reporting) + return -ENOMEM; + bitmap_set(cmn_node->status_reporting, 0, cmn_node->record_count); + + cmn_node->records = devm_kcalloc(adev->dev, cmn_node->record_count, + sizeof(struct aest_record), + GFP_KERNEL); + if (!cmn_node->records) + return -ENOMEM; + + aest_node_dbg(cmn_node, "Node init with errgsr %llx\n", errgsr_addr); + + return 0; +} + +static int aest_cmn_reorgnize_node(struct aest_device *adev, + struct acpi_aest_node *anode, u64 base) +{ + struct aest_node *cmn_node; + u64 hnd_offset, cmn_node_offset, reg, logic_id, type, node_id; + u64 errgsr_addr, hnd_base; + struct aest_record *record; + int ret, node_index; + struct cmn_vendor_data *vendor_data; + + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED) { + aest_dev_err(adev, "CMN just use single memory mapping\n"); + return -ENODEV; + } + + hnd_offset = *((u64 *)anode->vendor->vendor_specific_data); + cmn_node_offset = *((u64 *)&anode->vendor->vendor_specific_data[8]); + + reg = readq_relaxed((void *)base + cmn_node_offset + CMN_NODE_INFO); + + logic_id = FIELD_GET(CMN_NI_LOGICAL_ID, reg); + type = FIELD_GET(CMN_NI_NODE_TYPE, reg); + node_id = FIELD_GET(CMN_NI_NODE_ID, reg); + + hnd_base = base + hnd_offset; + node_index = cmn_config->node_id_map[type]; + errgsr_addr = base + cmn_config->errgsr_offset(hnd_offset, node_index); + + // node not register, create it + cmn_node = &adev->nodes[node_index]; + if (!cmn_node->errgsr) { + ret = aest_cmn_init_node(adev, cmn_node, anode, type, + errgsr_addr); + if (ret) + return -ENOMEM; + } + + aest_dev_dbg(adev, "node type %llx, id %llx, offset %llx\n", type, + logic_id, cmn_node_offset); + + if (!test_bit(0, anode->record_implemented)) + clear_bit(logic_id, cmn_node->record_implemented); + + if (!test_bit(0, anode->status_reporting)) + clear_bit(logic_id, cmn_node->status_reporting); + + record = &cmn_node->records[logic_id]; + record->name = + devm_kasprintf(adev->dev, GFP_KERNEL, "record%lld", logic_id); + if (!record->name) + return -ENOMEM; + record->regs_base = devm_ioremap( + adev->dev, (resource_size_t)anode->interface_hdr->address, + sizeof(struct ras_ext_regs)); + if (!record->regs_base) + return -ENOMEM; + record->addressing_mode = test_bit(0, anode->addressing_mode); + record->node = cmn_node; + record->index = logic_id; + record->access = &aest_access[anode->interface_hdr->type]; + + vendor_data = devm_kzalloc(adev->dev, sizeof(struct cmn_vendor_data), + GFP_KERNEL); + vendor_data->node_type = type; + vendor_data->node_id = node_id; + vendor_data->logic_id = logic_id; + + record->vendor_data = vendor_data; + record->vendor_data_size = sizeof(struct cmn_vendor_data); + + aest_record_dbg(record, "base %llx\n", anode->interface_hdr->address); + + return 0; +} + +// reorgnize cmn node +static int aest_cmn_probe(struct aest_device *adev, struct aest_hnode *ahnode) +{ + acpi_status status; + u64 base; + int ret = 0; + struct acpi_aest_node *anode; + char name[9]; + + anode = list_first_entry(&ahnode->list, struct acpi_aest_node, list); + if (!anode) + return -ENODEV; + + if (!cmn_dev_array[anode->vendor->acpi_uid]) { + snprintf(name, 9, "%s", anode->vendor->acpi_hid); + status = acpi_get_devices(name, aest_cmn_get_dev_by_uid, + &anode->vendor->acpi_uid, NULL); + if (ACPI_FAILURE(status)) { + aest_dev_err(adev, "Can not find base\n"); + return_ACPI_STATUS(status); + } + } + base = cmn_dev_array[anode->vendor->acpi_uid]; + if (!base) { + aest_dev_err(adev, "Device base invalid\n"); + return -ENODEV; + } + + adev->type = anode->type; + adev->node_cnt = cmn_config->dev_num; + adev->nodes = devm_kcalloc(adev->dev, adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!adev->nodes) + return -ENOMEM; + aest_set_name(adev, ahnode); + + list_for_each_entry(anode, &ahnode->list, list) { + ret = aest_cmn_reorgnize_node(adev, anode, base); + if (ret) + return ret; + } + + return 0; +} + +int aest_cmn700_probe(struct aest_device *adev, struct aest_hnode *ahnode) +{ + cmn_config = &cmn700_config; + + return aest_cmn_probe(adev, ahnode); +} diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 047c9a8cffe40..bbf8b1142be75 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -152,6 +152,8 @@ static void init_aest_event(struct aest_event *event, memcpy(&event->regs, regs, sizeof(*regs)); event->index = record->index; event->addressing_mode = record->addressing_mode; + event->vendor_data_size = record->vendor_data_size; + event->vendor_data = record->vendor_data; } static int aest_node_gen_pool_add(struct aest_device *adev, @@ -341,10 +343,9 @@ void aest_proc_record(struct aest_record *record, void *data, bool fake) record_write(record, ERXSTATUS, regs.err_status); } -static void aest_node_foreach_record(void (*func)(struct aest_record *, void *, - bool), - struct aest_node *node, void *data, - unsigned long *bitmap) +void aest_node_foreach_record(void (*func)(struct aest_record *, void *, bool), + struct aest_node *node, void *data, + unsigned long *bitmap) { int i; @@ -359,7 +360,7 @@ static void aest_node_foreach_record(void (*func)(struct aest_record *, void *, static int aest_proc(struct aest_node *node) { - int count = 0, i, j, size = node->record_count; + int count = 0, i, j, size = node->record_count, record_idx; u64 err_group = 0; aest_node_dbg(node, "Poll bitmap %*pb\n", size, @@ -374,19 +375,21 @@ static int aest_proc(struct aest_node *node) node->status_reporting); for (i = 0; i < BITS_TO_U64(size); i++) { err_group = readq_relaxed((void *)node->errgsr + i * 8); - aest_node_dbg(node, "errgsr[%d]: 0x%llx\n", i, err_group); - for_each_set_bit(j, (unsigned long *)&err_group, BITS_PER_LONG) { + record_idx = + node->errgsr_mapping(i * BITS_PER_LONG + j); + aest_node_dbg(node, "errgsr[%d]: bit %d occur error\n", + i, record_idx); /* * Error group base is only valid in Memory Map node, * so driver do not need to write select register and * sync. */ - if (test_bit(i * BITS_PER_LONG + j, - node->status_reporting)) + if (test_bit(record_idx, node->status_reporting)) continue; - aest_proc_record(&node->records[j], &count, false); + aest_proc_record(&node->records[record_idx], &count, + false); } } @@ -398,8 +401,11 @@ static irqreturn_t aest_irq_func(int irq, void *input) struct aest_device *adev = input; int i; - for (i = 0; i < adev->node_cnt; i++) + for (i = 0; i < adev->node_cnt; i++) { + if (!adev->nodes[i].record_count) + continue; aest_proc(&adev->nodes[i]); + } return IRQ_HANDLED; } @@ -776,6 +782,7 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, node->info = anode; node->type = anode->type; node->version = get_aest_node_ver(node); + node->errgsr_mapping = default_errgsr_mapping; node->name = alloc_aest_node_name(node); if (!node->name) return -ENOMEM; @@ -828,6 +835,7 @@ static int aest_init_node(struct aest_device *adev, struct aest_node *node, if (!node->records) return -ENOMEM; + node->errgsr_num = DIV_ROUND_UP(node->record_count, BITS_PER_LONG); for (i = 0; i < node->record_count; i++) { ret = aest_init_record(&node->records[i], i, node); if (ret) @@ -923,11 +931,12 @@ static int aest_setup_irq(struct platform_device *pdev, } static struct aest_vendor_match vendor_match[] = { - { }, + { "ARMHC700", &aest_cmn700_probe }, + {}, }; -static int -aest_vendor_probe(struct aest_device *adev, struct aest_hnode *ahnode) +static int aest_vendor_probe(struct aest_device *adev, + struct aest_hnode *ahnode) { int i; struct acpi_aest_node *anode; @@ -936,13 +945,14 @@ aest_vendor_probe(struct aest_device *adev, struct aest_hnode *ahnode) if (!anode) return -ENODEV; - aest_dev_dbg(adev, "Try to probe vendor node %s\n", anode->vendor->acpi_hid); + aest_dev_dbg(adev, "Try to probe vendor node %s\n", + anode->vendor->acpi_hid); for (i = 0; i < ARRAY_SIZE(vendor_match); i++) { if (!strncmp(vendor_match[i].hid, anode->vendor->acpi_hid, 8)) return vendor_match[i].probe(adev, ahnode); } - return -ENODEV; + return 0; } static int aest_device_probe(struct platform_device *pdev) diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 304c03839d31f..9d67d79eb4a2c 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -94,8 +94,16 @@ struct aest_event { /* Vendor node : hardware ID. */ char *hid; u32 index; + u64 ce_threshold; int addressing_mode; struct ras_ext_regs regs; + + /* + * This field is used to store vendor specific data for decoding error + * record by EDAC driver. + */ + void *vendor_data; + size_t vendor_data_size; }; struct aest_access { @@ -147,6 +155,9 @@ struct aest_record { enum ras_ce_threshold threshold_type; struct record_count count; struct dentry *debugfs; + + void *vendor_data; + size_t vendor_data_size; }; struct aest_group { @@ -208,6 +219,19 @@ struct aest_node { */ unsigned long *status_reporting; int version; + /* + * Usually bit[n] in errgsr indicates [n]th error record within this + * error node report error. But some compoent may have different rules. + * For example, CMN700 TRM 4.3.5.12 say: + * ``` Error occurs when the index is even and Fault + * occurs when the index is odd. ``` + * Bit[n]: record[n] report ERROR. + * Bit[n + 1]: record[n] report FAULT. + * errgsr_mapping function is used to map errgsr bit to record index + * for various components. + */ + int (*errgsr_mapping)(int errgsr_bit); + int errgsr_num; const struct aest_group *group; struct aest_device *adev; @@ -366,6 +390,21 @@ static inline bool aest_dev_is_oncore(struct aest_device *adev) return adev->type == ACPI_AEST_PROCESSOR_ERROR_NODE; } +static inline int default_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit; +} + +static inline int cmn700_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit / 2; +} + void aest_dev_init_debugfs(struct aest_device *adev); void aest_inject_init_debugfs(struct aest_record *record); void aest_proc_record(struct aest_record *record, void *data, bool fake); +void aest_node_foreach_record(void (*func)(struct aest_record *, void *, bool), + struct aest_node *node, void *data, + unsigned long *bitmap); + +int aest_cmn700_probe(struct aest_device *adev, struct aest_hnode *ahnode); From a8e6abdce1c794f1e04f1095c3bb65b76a4ea14c Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Thu, 22 Jan 2026 17:46:56 +0800 Subject: [PATCH 0367/1058] FROMLIST: trace, ras: add ARM RAS extension trace event Add a trace event for hardware errors reported by the ARMv8 RAS extension registers. userspace app can monitor this trace event and decode error information. Signed-off-by: Ruidong Tian Link: https://patch.msgid.link/20260122094656.73399-17-tianruidong@linux.alibaba.com Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 6 +++ drivers/ras/ras.c | 3 ++ include/ras/ras_event.h | 71 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index bbf8b1142be75..6a2d84b47721b 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -13,6 +13,8 @@ #include #include +#include + #include "aest.h" DEFINE_PER_CPU(struct aest_device, percpu_adev); @@ -90,6 +92,10 @@ static void aest_print(struct aest_event *event) pr_err("%s ERR%dMISC3: 0x%llx\n", pfx_seq, index, regs->err_misc[3]); } + + trace_arm_ras_ext_event(event->type, event->id0, event->id1, + event->index, event->hid, &event->regs, + event->vendor_data, event->vendor_data_size); } static void aest_handle_memory_failure(u64 addr) diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c index 03df3db623346..c8858b745021c 100644 --- a/drivers/ras/ras.c +++ b/drivers/ras/ras.c @@ -115,6 +115,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event); EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event); EXPORT_TRACEPOINT_SYMBOL_GPL(non_standard_event); EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event); +#ifdef CONFIG_ARM64_RAS_EXTN +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_ras_ext_event); +#endif static int __init parse_ras_param(char *str) { diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h index fdb785fa4613a..c4063f7ad7342 100644 --- a/include/ras/ras_event.h +++ b/include/ras/ras_event.h @@ -381,6 +381,77 @@ TRACE_EVENT(aer_event, "Not available") ); #endif /* CONFIG_PCIEAER */ + +/* + * ARM RAS Extension Events Report + * + * This event is generated when an error reported by the ARM RAS extension + * hardware is detected. + */ + +#ifdef CONFIG_ARM64_RAS_EXTN +#include +TRACE_EVENT(arm_ras_ext_event, + + TP_PROTO(const u8 type, + const u32 id0, + const u32 id1, + const u32 index, + char *hid, + struct ras_ext_regs *regs, + const u8 *data, + const u32 len), + + TP_ARGS(type, id0, id1, index, hid, regs, data, len), + + TP_STRUCT__entry( + __field(u8, type) + __field(u32, id0) + __field(u32, id1) + __field(u32, index) + __field(char *, hid) + __field(u64, err_fr) + __field(u64, err_ctlr) + __field(u64, err_status) + __field(u64, err_addr) + __field(u64, err_misc0) + __field(u64, err_misc1) + __field(u64, err_misc2) + __field(u64, err_misc3) + __field(u32, len) + __dynamic_array(u8, buf, len) + ), + + TP_fast_assign( + __entry->type = type; + __entry->id0 = id0; + __entry->id1 = id1; + __entry->index = index; + __entry->hid = hid; + __entry->err_fr = regs->err_fr; + __entry->err_ctlr = regs->err_ctlr; + __entry->err_status = regs->err_status; + __entry->err_addr = regs->err_addr; + __entry->err_misc0 = regs->err_misc[0]; + __entry->err_misc1 = regs->err_misc[1]; + __entry->err_misc2 = regs->err_misc[2]; + __entry->err_misc3 = regs->err_misc[3]; + __entry->len = len; + memcpy(__get_dynamic_array(buf), data, len); + ), + + TP_printk("type: %d; id0: %d; id1: %d; index: %d; hid: %s; " + "ERR_FR: %llx; ERR_CTLR: %llx; ERR_STATUS: %llx; " + "ERR_ADDR: %llx; ERR_MISC0: %llx; ERR_MISC1: %llx; " + "ERR_MISC2: %llx; ERR_MISC3: %llx; data len:%d; raw data:%s", + __entry->type, __entry->id0, __entry->id1, __entry->index, + __entry->hid, __entry->err_fr, __entry->err_ctlr, + __entry->err_status, __entry->err_addr, __entry->err_misc0, + __entry->err_misc1, __entry->err_misc2, __entry->err_misc3, + __entry->len, + __print_hex(__get_dynamic_array(buf), __entry->len)) +); +#endif /* CONFIG_ARM64_RAS_EXTN */ #endif /* _TRACE_HW_EVENT_MC_H */ /* This part must be outside protection */ From b75efe8922c5afd26b5f80b1ff36d9d965c866d4 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:45 +0530 Subject: [PATCH 0368/1058] FROMLIST: ras: aest: Fix shared processor node handling and error log messages Two related fixes for processor nodes with ACPI_AEST_PROC_FLAG_SHARED or ACPI_AEST_PROC_FLAG_GLOBAL set (e.g. cluster L3 cache, DSU): 1. aest_dev_is_oncore() returns true for any PROCESSOR_ERROR_NODE, causing shared processor nodes (which use an SPI) to take the cpuhp/PPI path. cpuhp_setup_state() is called instead of aest_online_dev(), so aest_config_irq() is never called and the hardware IRQ-config register is never programmed. Fix aest_dev_is_oncore() to check irq_is_percpu() on the registered IRQ. Only nodes whose FHI or ERI is a per-CPU PPI take the oncore path, nodes with an SPI take aest_online_dev(). 2. alloc_aest_node_name() uses processor_id for the node name of all processor nodes. Shared/global nodes have processor_id=0 (the field is unused when SHARED/GLOBAL is set), so every shared node and the per-PE node for CPU 0 both got the name "processor.0", making error logs ambiguous. For shared/global nodes, build the name as "processor.." (e.g. "processor.cache.1") so each node has a unique, meaningful identifier. Per-PE nodes keep the original "processor." form. Also add proc_flags to struct aest_event so aest_print() can distinguish shared from per-PE nodes and print an appropriate message. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-1-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 54 +++++++++++++++++++++++++++++++++--- drivers/ras/aest/aest.h | 15 +++++++++- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index 6a2d84b47721b..b4f4c975da1da 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -49,7 +49,19 @@ static void aest_print(struct aest_event *event) switch (event->type) { case ACPI_AEST_PROCESSOR_ERROR_NODE: - pr_err("%s Error from CPU%d\n", pfx_seq, event->id0); + /* + * For shared/global nodes (e.g. cluster L3 cache, DSU), + * id0 is the CPU that handled the interrupt — not the error + * source itself. The node_name already identifies the resource + * (e.g. "processor.cache.1"). Print a distinct message so the + * log is not confused with a per-PE CPU error. + */ + if (event->proc_flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) + pr_err("%s Error from shared processor resource (interrupt handled on CPU%d)\n", + pfx_seq, event->id0); + else + pr_err("%s Error from CPU%d\n", pfx_seq, event->id0); break; case ACPI_AEST_MEMORY_ERROR_NODE: pr_err("%s Error from memory at SRAT proximity domain %#x\n", @@ -133,6 +145,7 @@ static void init_aest_event(struct aest_event *event, info->processor->processor_id); event->id1 = info->processor->resource_type; + event->proc_flags = info->processor->flags; break; case ACPI_AEST_MEMORY_ERROR_NODE: event->id0 = info->memory->srat_proximity_domain; @@ -175,6 +188,7 @@ static int aest_node_gen_pool_add(struct aest_device *adev, if (!event) return -ENOMEM; + memset(event, 0, sizeof(*event)); init_aest_event(event, record, regs); llist_add(&event->llnode, &adev->event_list); @@ -730,9 +744,41 @@ static char *alloc_aest_node_name(struct aest_node *node) switch (node->type) { case ACPI_AEST_PROCESSOR_ERROR_NODE: - name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "%s.%d", - aest_node_name[node->type], - node->info->processor->processor_id); + /* + * Shared/global processor nodes (e.g. cluster L3 cache, DSU) + * have processor_id=0 and use smp_processor_id() at error-log + * time — using processor_id in the name would produce the same + * "processor.0" string for every shared node and every CPU0 + * per-PE node, making logs ambiguous. + * + * For shared/global nodes, build the name from the resource + * type and the device id so each node gets a unique, meaningful + * name (e.g. "processor.cache.1", "processor.tlb.2"). + * + * For per-PE nodes, keep the original "processor." form. + */ + if (node->info->processor->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) { + static const char *const res_name[] = { + [ACPI_AEST_CACHE_RESOURCE] = "cache", + [ACPI_AEST_TLB_RESOURCE] = "tlb", + [ACPI_AEST_GENERIC_RESOURCE] = "generic", + }; + u8 rtype = node->info->processor->resource_type; + const char *rstr = (rtype < ARRAY_SIZE(res_name) && + res_name[rtype]) ? res_name[rtype] : "unknown"; + + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, + "%s.%s.%d", + aest_node_name[node->type], + rstr, + node->adev->id); + } else { + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, + "%s.%d", + aest_node_name[node->type], + node->info->processor->processor_id); + } break; case ACPI_AEST_MEMORY_ERROR_NODE: case ACPI_AEST_SMMU_ERROR_NODE: diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h index 9d67d79eb4a2c..9704af97fee89 100644 --- a/drivers/ras/aest/aest.h +++ b/drivers/ras/aest/aest.h @@ -8,6 +8,7 @@ #include #include #include +#include #define MAX_GSI_PER_NODE 2 #define DEFAULT_CE_THRESHOLD 1 @@ -94,6 +95,8 @@ struct aest_event { /* Vendor node : hardware ID. */ char *hid; u32 index; + /* Processor node: ACPI_AEST_PROC_FLAG_* bitmask (SHARED/GLOBAL) */ + u8 proc_flags; u64 ce_threshold; int addressing_mode; struct ras_ext_regs regs; @@ -387,7 +390,17 @@ static inline void aest_sync(struct aest_node *node) static inline bool aest_dev_is_oncore(struct aest_device *adev) { - return adev->type == ACPI_AEST_PROCESSOR_ERROR_NODE; + /* + * A processor node is "on-core" (uses PPI + cpuhp) only when its + * interrupt is a per-CPU PPI. A shared processor node (e.g. cluster + * L3 cache, DSU) uses an SPI and must follow the non-oncore path + * (aest_online_dev) so that aest_config_irq and aest_online_dev are + * called instead of cpuhp_setup_state. + */ + if (adev->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return false; + return irq_is_percpu(adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]) || + irq_is_percpu(adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]); } static inline int default_errgsr_mapping(int errgsr_bit) From 2bf9823a8e6cc4d8ba0e46cce3d57c3a2fe84eb0 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:46 +0530 Subject: [PATCH 0369/1058] FROMLIST: ras: aest: Fix CE/UE error counts not incrementing in debugfs The error counts visible under: /sys/kernel/debug/aest//processor//err_count always reported zero, even though corrected errors (CEs) were being serviced by the interrupt handler. aest_oncore_dev_init_debugfs() sets up per CPU debugfs entries but wired them up incorrectly in two places: - this_cpu_ptr(adev->adev_oncore) was used inside for_each_possible_cpu(). This always selects the slot for the CPU executing the init code, so all debugfs files ended up referencing the same per CPU aest_device instance instead of the CPU indicated by the loop variable. - The code referenced adev->nodes[i], i.e. the template nodes allocated before __setup_ppi, rather than the per-CPU copies at percpu_dev->nodes[i]. The IRQ handler updates CE counters in the per-CPU records created by __setup_ppi, the template records are never touched at runtime, so err_count always read as zero. Fix this by: - Using per_cpu_ptr(adev->adev_oncore, cpu) when iterating over CPUs. Wiring debugfs files to percpu_dev->nodes[i] so counters reflect the data updated by the IRQ handler. - Using adev->nodes[i].name for debugfs directory names. The per-CPU node receives name via a shallow memcpy and is not the authoritative source. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-2-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-sysfs.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c index 66e9c1103f996..f710503e4d74a 100644 --- a/drivers/ras/aest/aest-sysfs.c +++ b/drivers/ras/aest/aest-sysfs.c @@ -189,16 +189,23 @@ aest_oncore_dev_init_debugfs(struct aest_device *adev) char name[16]; for_each_possible_cpu(cpu) { - percpu_dev = this_cpu_ptr(adev->adev_oncore); + percpu_dev = per_cpu_ptr(adev->adev_oncore, cpu); - snprintf(name, sizeof(name), "processor%u%u", cpu); + snprintf(name, sizeof(name), "processor%u", cpu); percpu_dev->debugfs = debugfs_create_dir(name, adev->debugfs); for (i = 0; i < adev->node_cnt; i++) { - node = &adev->nodes[i]; - - node->debugfs = debugfs_create_dir(node->name, - percpu_dev->debugfs); + node = &percpu_dev->nodes[i]; + + /* + * Use adev->nodes[i].name (the original) rather than + * node->name from the per-CPU copy. The per-CPU copy + * receives node->name via shallow memcpy in __setup_ppi; + * the original is the authoritative, guaranteed-valid + * string. + */ + node->debugfs = debugfs_create_dir(adev->nodes[i].name, + percpu_dev->debugfs); aest_node_init_debugfs(node); } } From 058e4183a1cd35a04832f12b98cee49fe0287ba3 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:47 +0530 Subject: [PATCH 0370/1058] FROMLIST: ras: aest: Skip unimplemented records in debugfs The record_implemented bitmap uses the same semantics as the rest of the driver: a SET bit means the record is NOT implemented (skip it), a CLEAR bit means the record IS implemented (process it). aest_node_init_debugfs() and aest_node_err_count_show() were iterating all record_count records unconditionally, creating debugfs entries and accumulating error counts for unimplemented records too. Fix both functions to skip records where the corresponding bit is set in node->record_implemented, consistent with how aest_node_foreach_record() handles the same bitmap. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-3-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-sysfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c index f710503e4d74a..b36190bb3b3e4 100644 --- a/drivers/ras/aest/aest-sysfs.c +++ b/drivers/ras/aest/aest-sysfs.c @@ -52,7 +52,8 @@ static int aest_node_err_count_show(struct seq_file *m, void *data) int i; for (i = 0; i < node->record_count; i++) - aest_error_count(&node->records[i], &count); + if (!test_bit(i, node->record_implemented)) + aest_error_count(&node->records[i], &count); seq_printf(m, "CE: %llu\n" "DE: %llu\n" @@ -174,8 +175,11 @@ aest_node_init_debugfs(struct aest_node *node) record = &node->records[i]; if (!record->name) continue; + /* Skip records not implemented on this node. */ + if (test_bit(i, node->record_implemented)) + continue; record->debugfs = debugfs_create_dir(record->name, - node->debugfs); + node->debugfs); aest_record_init_debugfs(record); } } From 1e79c32f7a8e84c95c56dad47aed862385be116d Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:48 +0530 Subject: [PATCH 0371/1058] FROMLIST: ras: aest: Add panic_on_ue module parameter The driver unconditionally calls panic() whenever an unrecoverable, uncontainable UE (UET_UC or UET_UEU) is detected. There is no way for the user to suppress this behaviour, which makes it difficult to test UE injection or to run in environments where a kernel panic on every UE is undesirable. Add a module parameter `aest_panic_on_ue` When set to 0 the driver logs the UE and continues instead of panicking. Usage: # Boot time (kernel cmdline) aest.aest_panic_on_ue=0 # Runtime echo 0 > /sys/module/aest/parameters/aest_panic_on_ue Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-4-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- drivers/ras/aest/aest-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c index b4f4c975da1da..9ce782a66edfc 100644 --- a/drivers/ras/aest/aest-core.c +++ b/drivers/ras/aest/aest-core.c @@ -22,6 +22,11 @@ DEFINE_PER_CPU(struct aest_device, percpu_adev); #undef pr_fmt #define pr_fmt(fmt) "AEST: " fmt +static bool aest_panic_on_ue; +module_param(aest_panic_on_ue, bool, 0644); +MODULE_PARM_DESC(aest_panic_on_ue, + "Panic on unrecoverable error: 0=off 1=on (default: 1)"); + #ifdef CONFIG_DEBUG_FS struct dentry *aest_debugfs; #endif @@ -342,9 +347,11 @@ void aest_proc_record(struct aest_record *record, void *data, bool fake) aest_record_info( record, "Simulated error! Skip panic due to fault injection\n"); - else + else if (aest_panic_on_ue) aest_panic(record, ®s, "AEST: unrecoverable error encountered"); + else + aest_record_err(record, "UE detected, panic suppressed\n"); } aest_log(record, ®s); From 1c7430f1d489e0de7d00a0730f4d653e328bc287 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:49 +0530 Subject: [PATCH 0372/1058] FROMLIST: dt-bindings: arm: ras: Introduce bindings for ARM AEST The Arm Error Source Table (AEST) specification describes how firmware exposes RAS error source topology to the operating system. On ACPI systems this information is provided via the AEST ACPI table. Introduce Device Tree bindings that provide an equivalent description of AEST error sources for DT-based platforms. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-5-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- .../devicetree/bindings/arm/arm,aest.yaml | 406 ++++++++++++++++++ include/dt-bindings/arm/aest.h | 43 ++ 2 files changed, 449 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,aest.yaml create mode 100644 include/dt-bindings/arm/aest.h diff --git a/Documentation/devicetree/bindings/arm/arm,aest.yaml b/Documentation/devicetree/bindings/arm/arm,aest.yaml new file mode 100644 index 0000000000000..7809a0d382703 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,aest.yaml @@ -0,0 +1,406 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,aest.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Arm Error Source Table (AEST) + +maintainers: + - Umang Chheda + +description: + The Arm Error Source Table (AEST) describes RAS error sources and their + register interfaces. Each error source exposes one or more error records + through either system registers or a memory-mapped register window, and + may signal errors via interrupts. The top-level node acts as a container + for one or more child nodes, each describing a single AEST error source. + Refer to the Arm AEST specification (DEN0085 / DDI 0587B) for details. + Flag bit constants for use in DT source files are defined in + . + +properties: + compatible: + const: arm,aest + + "#address-cells": + const: 2 + + "#size-cells": + const: 2 + + ranges: true + +required: + - compatible + +additionalProperties: false + +patternProperties: + "^aest-[a-z0-9-]+(@[0-9a-f]+)?$": + type: object + description: + An AEST error source node describing one error source defined by + the Arm AEST specification. + + properties: + compatible: + description: + Identifies the type of AEST error source. Each value corresponds to + a distinct error source class defined by the Arm AEST specification. + arm,aest-proxy represents a proxy error source that forwards errors + from another error source. + enum: + - arm,aest-processor + - arm,aest-memory + - arm,aest-smmu + - arm,aest-gic + - arm,aest-pcie + - arm,aest-vendor + - arm,aest-proxy + + reg: + description: + Register ranges for the error source. Absence of reg implies + system-register access (interface type 0). A single range implies + memory-mapped access (interface type 1). Two ranges imply + single-record memory-mapped access (interface type 2). + minItems: 1 + maxItems: 4 + + reg-names: + description: + Names for the register ranges. The base error-record window is + unnamed (or first entry). Optional named ranges provide access to + the fault-injection, error-group, and interrupt-config register + windows defined by the AEST specification. + minItems: 1 + maxItems: 4 + items: + enum: + - fault-inject + - err-group + - irq-config + + interrupts: + description: Interrupts associated with the error source. + minItems: 1 + maxItems: 2 + + interrupt-names: + description: Names of the interrupts associated with the error source. + minItems: 1 + maxItems: 2 + items: + enum: + - fhi + - eri + + arm,fhi-flags: + description: + Bitmask of flags for the fault-handling interrupt (FHI), as defined + in the AEST node interrupt structure flags field. Constants are + defined in - AEST_IRQ_MODE_LEVEL (0), + AEST_IRQ_MODE_EDGE (1). + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,eri-flags: + description: + Bitmask of flags for the error-recovery interrupt (ERI), as defined + in the AEST node interrupt structure flags field. Constants are + defined in . + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,interface-flags: + description: | + Bitmask of interface flags for the error source, as defined in the + AEST node interface flags field. Constants are defined in + : + AEST_XFACE_SHARED (bit 0) - shared error source, + AEST_XFACE_CLEAR_MISC (bit 1) - clear MISC registers on error, + AEST_XFACE_ERROR_DEVICE (bit 2) - error node device present, + AEST_XFACE_AFFINITY (bit 3) - affinity information valid, + AEST_XFACE_ERROR_GROUP (bit 4) - error group register window present, + AEST_XFACE_FAULT_INJECT (bit 5) - fault injection register window present, + AEST_XFACE_INT_CONFIG (bit 6) - interrupt config register window present. + For system-register interface nodes (no reg property), only + AEST_XFACE_CLEAR_MISC is meaningful; the MMIO window flags + (AEST_XFACE_ERROR_GROUP, AEST_XFACE_FAULT_INJECT, + AEST_XFACE_INT_CONFIG) have no effect without a base address. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,group-format: + description: | + Page-granularity of the error record group register window, which + determines the MMIO mapping size, the number of ERRGSR registers, + and the width of the record-implemented and status-reporting bitmaps. + Constants are defined in : + AEST_GROUP_FORMAT_4K (0) - 4K window, 1 ERRGSR, up to 64 records, + AEST_GROUP_FORMAT_16K (1) - 16K window, 4 ERRGSRs, up to 256 records, + AEST_GROUP_FORMAT_64K (2) - 64K window, 14 ERRGSRs, up to 896 records. + Required for memory-mapped nodes (reg present) where it controls + the ioremap size and ERRGSR layout. For system-register nodes + (no reg property) this property is optional and defaults to + AEST_GROUP_FORMAT_4K. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + arm,num-records: + description: Number of error records implemented by this error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,record-impl: + description: + Bitmap of implemented error records within this error source. Bit N + set to 0 means error record N is implemented and must be polled. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,status-reporting: + description: + Bitmap indicating which error records support status reporting via + the ERRGSR register. Bit N set to 1 means record N does not report + through ERRGSR and must be polled explicitly. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,addressing-mode: + description: + Bitmap indicating the address type reported in ERR_ADDR for each + error record. Bit N set to 0 means record N reports System Physical + Addresses (SPA); bit N set to 1 means record N reports node-specific + Logical Addresses (LA) that require OS translation to SPA. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,processor-flags: + description: + Bitmask indicating the scope of a processor error source, as defined + in the AEST processor node flags field. Constants are defined in + - AEST_PROC_GLOBAL (bit 0), + AEST_PROC_SHARED (bit 1). + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,resource-type: + description: | + Type of processor resource associated with this error source. + Constants are defined in : + AEST_RESOURCE_CACHE (0), + AEST_RESOURCE_TLB (1), + AEST_RESOURCE_GENERIC (2). + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + arm,cache-ref: + description: + Phandle to the cache node associated with this processor error source. + $ref: /schemas/types.yaml#/definitions/phandle + + arm,tlb-level: + description: TLB level identifier for this processor TLB error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,resource-ref: + description: + Generic resource reference identifier for this processor error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,proximity-domain: + description: + SRAT proximity domain of the memory node associated with this error + source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,smmu-ref: + description: + Phandle to the SMMU node in the IORT associated with this error + source. + $ref: /schemas/types.yaml#/definitions/phandle + + arm,smmu-subcomponent: + description: + SMMU subcomponent reference identifier for this error source, as + defined in the AEST SMMU node structure. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,gic-type: + description: | + GIC component type for this error source, as defined in the AEST GIC + node structure. Constants are defined in : + AEST_GIC_CPU (0), + AEST_GIC_DISTRIBUTOR (1), + AEST_GIC_REDISTRIBUTOR (2), + AEST_GIC_ITS (3). + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + arm,gic-instance: + description: + GIC instance identifier for this error source, used to distinguish + multiple instances of the same GIC component type. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,pcie-segment: + description: + PCI segment number of the PCIe root port associated with this error + source, corresponding to the IORT node reference. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,vendor-hid: + description: + 8-character ACPI Hardware ID string identifying the vendor error + source, as defined in the AEST vendor node structure. + $ref: /schemas/types.yaml#/definitions/string + + arm,vendor-uid: + description: + ACPI unique instance identifier for this vendor error source, used + to distinguish multiple instances with the same hardware ID. + $ref: /schemas/types.yaml#/definitions/uint32 + + required: + - compatible + - arm,num-records + + allOf: + - if: + required: + - reg + then: + required: + - arm,group-format + - if: + properties: + compatible: + contains: + const: arm,aest-processor + then: + properties: + arm,processor-flags: {} + arm,resource-type: {} + arm,cache-ref: {} + arm,tlb-level: {} + arm,resource-ref: {} + else: + properties: + arm,processor-flags: false + arm,resource-type: false + arm,cache-ref: false + arm,tlb-level: false + arm,resource-ref: false + + - if: + properties: + compatible: + contains: + const: arm,aest-memory + then: + required: + - arm,proximity-domain + properties: + arm,proximity-domain: {} + else: + properties: + arm,proximity-domain: false + + - if: + properties: + compatible: + contains: + const: arm,aest-smmu + then: + required: + - arm,smmu-ref + properties: + arm,smmu-ref: {} + arm,smmu-subcomponent: {} + else: + properties: + arm,smmu-ref: false + arm,smmu-subcomponent: false + + - if: + properties: + compatible: + contains: + const: arm,aest-gic + then: + properties: + arm,gic-type: {} + arm,gic-instance: {} + else: + properties: + arm,gic-type: false + arm,gic-instance: false + + - if: + properties: + compatible: + contains: + const: arm,aest-pcie + then: + required: + - arm,pcie-segment + properties: + arm,pcie-segment: {} + else: + properties: + arm,pcie-segment: false + + - if: + properties: + compatible: + contains: + const: arm,aest-vendor + then: + required: + - arm,vendor-hid + properties: + arm,vendor-hid: {} + arm,vendor-uid: {} + else: + properties: + arm,vendor-hid: false + arm,vendor-uid: false + + unevaluatedProperties: false + +examples: + - | + #include + #include + + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + + /* System-register based processor error source (no reg property) */ + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x3>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + arm,resource-type = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + /* Memory-mapped memory controller error source */ + aest-memory-0@50010000 { + compatible = "arm,aest-memory"; + reg = <0x0 0x50010000 0x0 0x1000>, + <0x0 0x50011000 0x0 0x1000>, + <0x0 0x50012000 0x0 0x1000>; + reg-names = "err-group", "fault-inject", "irq-config"; + arm,group-format = ; + arm,num-records = <4>; + arm,record-impl = /bits/ 64 <0xf>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,interface-flags = ; + arm,proximity-domain = <0>; + interrupts = , + ; + interrupt-names = "fhi", "eri"; + }; + }; diff --git a/include/dt-bindings/arm/aest.h b/include/dt-bindings/arm/aest.h new file mode 100644 index 0000000000000..43679314e98e8 --- /dev/null +++ b/include/dt-bindings/arm/aest.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * This header provides constants for the Arm Error Source Table (AEST) + * DT binding (Documentation/devicetree/bindings/arm/arm,aest.yaml). + */ + +#ifndef _DT_BINDINGS_ARM_AEST_H +#define _DT_BINDINGS_ARM_AEST_H + +/* arm,interface-flags - AEST node interface flags field */ +#define AEST_XFACE_SHARED 1 +#define AEST_XFACE_CLEAR_MISC 2 +#define AEST_XFACE_ERROR_DEVICE 4 +#define AEST_XFACE_AFFINITY 8 +#define AEST_XFACE_ERROR_GROUP 16 +#define AEST_XFACE_FAULT_INJECT 32 +#define AEST_XFACE_INT_CONFIG 64 + +/* arm,fhi-flags / arm,eri-flags - AEST node interrupt flags field */ +#define AEST_IRQ_MODE_LEVEL 0 +#define AEST_IRQ_MODE_EDGE 1 + +/* arm,processor-flags - AEST processor node flags field */ +#define AEST_PROC_GLOBAL 1 +#define AEST_PROC_SHARED 2 + +/* arm,group-format - error record group register window page size */ +#define AEST_GROUP_FORMAT_4K 0 +#define AEST_GROUP_FORMAT_16K 1 +#define AEST_GROUP_FORMAT_64K 2 + +/* arm,resource-type - processor resource type */ +#define AEST_RESOURCE_CACHE 0 +#define AEST_RESOURCE_TLB 1 +#define AEST_RESOURCE_GENERIC 2 + +/* arm,gic-type - GIC component type */ +#define AEST_GIC_CPU 0 +#define AEST_GIC_DISTRIBUTOR 1 +#define AEST_GIC_REDISTRIBUTOR 2 +#define AEST_GIC_ITS 3 + +#endif /* _DT_BINDINGS_ARM_AEST_H */ From 600ea9c656eedd9961e311ec6c0c252ed046221f Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:50 +0530 Subject: [PATCH 0373/1058] FROMLIST: ras: aest: Add DT frontend for ARM AEST RAS error sources Add a Device Tree frontend for the Arm AEST RAS framework, allowing the existing AEST core driver to be used on DT-only systems. The DT frontend parses the "arm,aest" Device Tree hierarchy and populates the same internal structures as the ACPI-based implementation. It is initialized at the same layer as ACPI and is mutually exclusive with it, ensuring identical behaviour regardless of the firmware interface in use. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-6-d5d6ffacf0a5@oss.qualcomm.com/ Signed-off-by: Umang Chheda --- drivers/ras/aest/Kconfig | 15 +- drivers/ras/aest/Makefile | 2 + drivers/ras/aest/aest-of.c | 673 +++++++++++++++++++++++++++++++++++++ 3 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 drivers/ras/aest/aest-of.c diff --git a/drivers/ras/aest/Kconfig b/drivers/ras/aest/Kconfig index 0b09a5d5acce3..ca034255faddf 100644 --- a/drivers/ras/aest/Kconfig +++ b/drivers/ras/aest/Kconfig @@ -7,11 +7,22 @@ config AEST tristate "ARM AEST Driver" - depends on ACPI_AEST && RAS - + depends on ACPI_AEST || OF_AEST + depends on RAS help The Arm Error Source Table (AEST) provides details on ACPI extensions that enable kernel-first handling of errors in a system that supports the Armv8 RAS extensions. If set, the kernel will report and log hardware errors. + +config OF_AEST + bool "ARM Error Source Table DT Support" + depends on ARM64_RAS_EXTN && OF + help + Enable support for discovering ARM RAS error sources using the + Device Tree based Arm Error Source Table (AEST) specification. + This allows the kernel to enumerate and manage hardware error + reporting blocks described in firmware for ARMv8 and later + systems. Select this option if your platform describes AEST + nodes in Device Tree and relies on RAS error handling. diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile index e5a45fde6d362..2997952901c05 100644 --- a/drivers/ras/aest/Makefile +++ b/drivers/ras/aest/Makefile @@ -6,3 +6,5 @@ aest-y := aest-core.o aest-y += aest-sysfs.o aest-y += aest-inject.o aest-y += aest-cmn.o + +obj-$(CONFIG_OF_AEST) += aest-of.o diff --git a/drivers/ras/aest/aest-of.c b/drivers/ras/aest/aest-of.c new file mode 100644 index 0000000000000..939db2c417427 --- /dev/null +++ b/drivers/ras/aest/aest-of.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +#undef pr_fmt +#define pr_fmt(fmt) "DT AEST: " fmt + +struct dt_aest_priv { + struct xarray aest_array; + u32 node_id; +}; + +static const struct of_device_id dt_aest_child_match[] = { + { .compatible = "arm,aest-processor", .data = (void *)ACPI_AEST_PROCESSOR_ERROR_NODE }, + { .compatible = "arm,aest-memory", .data = (void *)ACPI_AEST_MEMORY_ERROR_NODE }, + { .compatible = "arm,aest-smmu", .data = (void *)ACPI_AEST_SMMU_ERROR_NODE }, + { .compatible = "arm,aest-vendor", .data = (void *)ACPI_AEST_VENDOR_ERROR_NODE }, + { .compatible = "arm,aest-gic", .data = (void *)ACPI_AEST_GIC_ERROR_NODE }, + { .compatible = "arm,aest-pcie", .data = (void *)ACPI_AEST_PCIE_ERROR_NODE }, + { .compatible = "arm,aest-proxy", .data = (void *)ACPI_AEST_PROXY_ERROR_NODE }, + { } +}; + +static int dt_aest_node_type(struct device_node *np) +{ + const struct of_device_id *match; + + match = of_match_node(dt_aest_child_match, np); + if (!match) { + pr_warn("unknown compatible for %pOF\n", np); + return -EINVAL; + } + return (int)(uintptr_t)match->data; +} + +static struct aest_hnode *dt_aest_alloc_hnode(int node_type, u32 id) +{ + struct aest_hnode *ahnode; + + ahnode = kzalloc_obj(*ahnode, GFP_KERNEL); + if (!ahnode) + return NULL; + + INIT_LIST_HEAD(&ahnode->list); + ahnode->count = 0; + ahnode->id = id; + ahnode->type = node_type; + return ahnode; +} + +static int dt_aest_build_interface(struct device_node *np, + struct acpi_aest_node *anode) +{ + struct acpi_aest_node_interface_header *hdr; + struct acpi_aest_node_interface_common *common; + struct resource res; + struct resource named_res; + u32 gfmt = 0, flags = 0, nrec = 1; + u32 itype; + int ret; + size_t body_sz; + + /* + * Deduce interface type from the presence and count of reg entries: + * no reg -> system-register access (type 0) + * 1 range -> memory-mapped access (type 1) + * 2+ ranges -> single-record MMIO (type 2) + */ + if (!of_property_present(np, "reg")) + itype = ACPI_AEST_NODE_SYSTEM_REGISTER; + else if (of_property_count_elems_of_size(np, "reg", sizeof(u32)) <= + (of_n_addr_cells(np) + of_n_size_cells(np))) + itype = ACPI_AEST_NODE_MEMORY_MAPPED; + else + itype = ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED; + + of_property_read_u32(np, "arm,group-format", &gfmt); + of_property_read_u32(np, "arm,interface-flags", &flags); + of_property_read_u32(np, "arm,num-records", &nrec); + + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + body_sz = sizeof(struct acpi_aest_node_interface_16k); + break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + body_sz = sizeof(struct acpi_aest_node_interface_64k); + break; + default: + body_sz = sizeof(struct acpi_aest_node_interface_4k); + break; + } + + hdr = kzalloc(sizeof(*hdr) + body_sz, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + /* Fill header */ + hdr->type = (u8)itype; + hdr->group_format = (u8)gfmt; + hdr->flags = flags; + hdr->error_record_count = nrec; + hdr->error_record_index = 0; + + if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) { + ret = of_address_to_resource(np, 0, &res); + if (ret) { + pr_err("node %pOF: missing 'reg' for MMIO interface\n", np); + kfree(hdr); + return ret; + } + hdr->address = res.start; + } + + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: { + struct acpi_aest_node_interface_4k *b = + (struct acpi_aest_node_interface_4k *)(hdr + 1); + of_property_read_u64(np, "arm,record-impl", + &b->error_record_implemented); + of_property_read_u64(np, "arm,status-reporting", + &b->error_status_reporting); + of_property_read_u64(np, "arm,addressing-mode", + &b->addressing_mode); + common = &b->common; + anode->record_implemented = + (unsigned long *)&b->error_record_implemented; + anode->status_reporting = + (unsigned long *)&b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)&b->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_16K: { + struct acpi_aest_node_interface_16k *b = + (struct acpi_aest_node_interface_16k *)(hdr + 1); + of_property_read_u64_array(np, "arm,record-impl", + b->error_record_implemented, 4); + of_property_read_u64_array(np, "arm,status-reporting", + b->error_status_reporting, 4); + of_property_read_u64_array(np, "arm,addressing-mode", + b->addressing_mode, 4); + common = &b->common; + anode->record_implemented = + (unsigned long *)b->error_record_implemented; + anode->status_reporting = + (unsigned long *)b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)b->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_64K: { + struct acpi_aest_node_interface_64k *b = + (struct acpi_aest_node_interface_64k *)(hdr + 1); + of_property_read_u64_array(np, "arm,record-impl", + b->error_record_implemented, 14); + of_property_read_u64_array(np, "arm,status-reporting", + b->error_status_reporting, 14); + of_property_read_u64_array(np, "arm,addressing-mode", + b->addressing_mode, 14); + common = &b->common; + anode->record_implemented = + (unsigned long *)b->error_record_implemented; + anode->status_reporting = + (unsigned long *)b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)b->addressing_mode; + break; + } + default: + pr_err("node %pOF: unsupported group-format %u\n", np, gfmt); + kfree(hdr); + return -EINVAL; + } + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "fault-inject"), &named_res)) + common->fault_inject_register_base = named_res.start; + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "err-group"), &named_res)) + common->error_group_register_base = named_res.start; + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "irq-config"), &named_res)) + common->interrupt_config_register_base = named_res.start; + + anode->interface_hdr = hdr; + anode->common = common; + + return 0; +} + +static int dt_aest_build_interrupt(struct device_node *np, + struct acpi_aest_node *anode) +{ + struct acpi_aest_node_interrupt_v2 *irq_arr; + int fhi_irq, eri_irq, count = 0; + u32 fhi_flags = 0, eri_flags = 0; + + of_property_read_u32(np, "arm,fhi-flags", &fhi_flags); + of_property_read_u32(np, "arm,eri-flags", &eri_flags); + + fhi_irq = of_irq_get_byname(np, "fhi"); + if (fhi_irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (fhi_irq < 0 && fhi_irq != -EINVAL) { + const char *name = NULL; + + of_property_read_string(np, "interrupt-names", &name); + + pr_warn("node %pOF: failed to map FHI IRQ: %d (interrupt-names[0]=\"%s\", want \"%s\")\n", + np, fhi_irq, name ?: "", "fhi"); + } + eri_irq = of_irq_get_byname(np, "eri"); + if (eri_irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (eri_irq < 0 && eri_irq != -EINVAL) { + const char *name = NULL; + + of_property_read_string_index(np, "interrupt-names", 1, &name); + + pr_warn("node %pOF: failed to map ERI IRQ: %d (interrupt-names[1]=\"%s\", want \"%s\")\n", + np, eri_irq, name ?: "", "eri"); + } + + if (fhi_irq > 0) + count++; + if (eri_irq > 0) + count++; + + if (!count) { + anode->interrupt = NULL; + anode->interrupt_count = 0; + return 0; + } + + irq_arr = kcalloc(count, sizeof(*irq_arr), GFP_KERNEL); + if (!irq_arr) + return -ENOMEM; + + count = 0; + if (fhi_irq > 0) { + irq_arr[count].gsiv = fhi_irq; + irq_arr[count].flags = AEST_INTERRUPT_MODE | fhi_flags; + irq_arr[count].type = ACPI_AEST_NODE_FAULT_HANDLING; + count++; + } + if (eri_irq > 0) { + irq_arr[count].gsiv = eri_irq; + irq_arr[count].flags = eri_flags; + irq_arr[count].type = ACPI_AEST_NODE_ERROR_RECOVERY; + count++; + } + + anode->interrupt = irq_arr; + anode->interrupt_count = count; + return 0; +} + +static int dt_aest_build_node_specific(struct device_node *np, + struct acpi_aest_node *anode, + int node_type) +{ + switch (node_type) { + + case ACPI_AEST_PROCESSOR_ERROR_NODE: { + struct acpi_aest_processor *proc; + u32 rtype = 0, pflags = 0; + + proc = kzalloc_obj(*proc, GFP_KERNEL); + if (!proc) + return -ENOMEM; + + of_property_read_u32(np, "arm,resource-type", &rtype); + of_property_read_u32(np, "arm,processor-flags", &pflags); + + proc->resource_type = (u8)rtype; + proc->flags = (u8)pflags; + + /* Processor cache/TLB/generic sub-structure */ + switch (rtype) { + case ACPI_AEST_CACHE_RESOURCE: { + struct acpi_aest_processor_cache *c; + struct device_node *cache_np; + + c = kzalloc_obj(*c, GFP_KERNEL); + if (!c) { + kfree(proc); + return -ENOMEM; + } + + cache_np = of_parse_phandle(np, "arm,cache-ref", 0); + if (cache_np) { + c->cache_reference = cache_np->phandle; + of_node_put(cache_np); + } + anode->cache = c; + break; + } + case ACPI_AEST_TLB_RESOURCE: { + struct acpi_aest_processor_tlb *t; + + t = kzalloc_obj(*t, GFP_KERNEL); + if (!t) { + kfree(proc); + return -ENOMEM; + } + of_property_read_u32(np, "arm,tlb-level", + &t->tlb_level); + anode->tlb = t; + break; + } + default: { + struct acpi_aest_processor_generic *g; + + g = kzalloc_obj(*g, GFP_KERNEL); + if (!g) { + kfree(proc); + return -ENOMEM; + } + of_property_read_u32(np, "arm,resource-ref", + &g->resource); + anode->generic = g; + break; + } + } + anode->processor = proc; + break; + } + + case ACPI_AEST_MEMORY_ERROR_NODE: { + struct acpi_aest_memory *mem; + + mem = kzalloc_obj(*mem, GFP_KERNEL); + + if (!mem) + return -ENOMEM; + of_property_read_u32(np, "arm,proximity-domain", + &mem->srat_proximity_domain); + anode->memory = mem; + break; + } + + case ACPI_AEST_SMMU_ERROR_NODE: { + struct acpi_aest_smmu *smmu; + struct device_node *smmu_np; + + smmu = kzalloc_obj(*smmu, GFP_KERNEL); + + if (!smmu) + return -ENOMEM; + smmu_np = of_parse_phandle(np, "arm,smmu-ref", 0); + if (smmu_np) { + /* Use the DT node offset as the IORT reference */ + smmu->iort_node_reference = smmu_np->phandle; + of_node_put(smmu_np); + } + of_property_read_u32(np, "arm,smmu-subcomponent", + &smmu->subcomponent_reference); + anode->smmu = smmu; + break; + } + + case ACPI_AEST_VENDOR_ERROR_NODE: { + struct acpi_aest_vendor_v2 *vendor; + const char *hid = "ARMHC000"; + + vendor = kzalloc_obj(*vendor, GFP_KERNEL); + + if (!vendor) + return -ENOMEM; + of_property_read_string(np, "arm,vendor-hid", &hid); + strscpy(vendor->acpi_hid, hid, sizeof(vendor->acpi_hid)); + of_property_read_u32(np, "arm,vendor-uid", + &vendor->acpi_uid); + anode->vendor = vendor; + break; + } + + case ACPI_AEST_GIC_ERROR_NODE: { + struct acpi_aest_gic *gic; + + gic = kzalloc_obj(*gic, GFP_KERNEL); + + if (!gic) + return -ENOMEM; + of_property_read_u32(np, "arm,gic-type", + &gic->interface_type); + of_property_read_u32(np, "arm,gic-instance", + &gic->instance_id); + anode->gic = gic; + break; + } + + case ACPI_AEST_PCIE_ERROR_NODE: { + struct acpi_aest_pcie *pcie; + + pcie = kzalloc_obj(*pcie, GFP_KERNEL); + + if (!pcie) + return -ENOMEM; + of_property_read_u32(np, "arm,pcie-segment", + &pcie->iort_node_reference); + anode->pcie = pcie; + break; + } + + case ACPI_AEST_PROXY_ERROR_NODE: + /* No node-specific data for proxy nodes */ + anode->spec_pointer = NULL; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static struct acpi_aest_node * +dt_aest_alloc_anode(struct device_node *np, int node_type) +{ + struct acpi_aest_node *anode; + int ret; + + anode = kzalloc_obj(*anode, GFP_KERNEL); + if (!anode) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&anode->list); + anode->type = node_type; + + ret = dt_aest_build_interface(np, anode); + if (ret) + goto err_free; + + ret = dt_aest_build_node_specific(np, anode, node_type); + if (ret) + goto err_free; + + ret = dt_aest_build_interrupt(np, anode); + if (ret) + goto err_free; + + return anode; + +err_free: + kfree(anode->interface_hdr); + kfree(anode->spec_pointer); + kfree(anode->processor_spec_pointer); + kfree(anode); + return ERR_PTR(ret); +} + +static int dt_aest_init_one_node(struct device_node *np, + struct dt_aest_priv *priv) +{ + int node_type; + struct aest_hnode *ahnode; + struct acpi_aest_node *anode; + + node_type = dt_aest_node_type(np); + if (node_type < 0) { + pr_warn("unknown node type for %pOF, skipping\n", np); + return 0; + } + + ahnode = dt_aest_alloc_hnode(node_type, priv->node_id); + if (!ahnode) + return -ENOMEM; + + anode = dt_aest_alloc_anode(np, node_type); + if (IS_ERR(anode)) { + kfree(ahnode); + return PTR_ERR(anode); + } + + list_add_tail(&anode->list, &ahnode->list); + ahnode->count = 1; + + if (xa_err(xa_store(&priv->aest_array, priv->node_id, + ahnode, GFP_KERNEL))) { + kfree(anode); + kfree(ahnode); + return -ENOMEM; + } + priv->node_id++; + return 0; +} + +static int dt_aest_init_nodes(struct device_node *aest_root, + struct dt_aest_priv *priv) +{ + struct device_node *np; + int ret; + + for_each_available_child_of_node(aest_root, np) { + ret = dt_aest_init_one_node(np, priv); + if (ret) { + pr_err("failed to init node %pOF: %d\n", np, ret); + of_node_put(np); + return ret; + } + } + return 0; +} + +static struct platform_device *dt_aest_alloc_pdev(struct aest_hnode *ahnode, + int index) +{ + struct platform_device *pdev; + struct resource *res; + struct acpi_aest_node *anode; + int ret, size, j; + int irq[AEST_MAX_INTERRUPT_PER_NODE] = { 0 }; + + pdev = platform_device_alloc("AEST", index); + if (!pdev) + return ERR_PTR(-ENOMEM); + + res = kcalloc(ahnode->count + AEST_MAX_INTERRUPT_PER_NODE, + sizeof(*res), GFP_KERNEL); + if (!res) { + platform_device_put(pdev); + return ERR_PTR(-ENOMEM); + } + + j = 0; + list_for_each_entry(anode, &ahnode->list, list) { + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SYSTEM_REGISTER) { + res[j].name = AEST_NODE_NAME; + res[j].start = anode->interface_hdr->address; + + switch (anode->interface_hdr->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: + size = 4 * KB; break; + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + size = 16 * KB; break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + size = 64 * KB; break; + default: + size = 4 * KB; + } + res[j].end = res[j].start + size - 1; + res[j].flags = IORESOURCE_MEM; + j++; + } + + if (anode->interrupt && anode->interrupt_count > 0) { + int k; + + for (k = 0; k < anode->interrupt_count && + k < AEST_MAX_INTERRUPT_PER_NODE; k++) { + + struct acpi_aest_node_interrupt_v2 *intr = + &anode->interrupt[k]; + int itype = intr->type; + int virq = intr->gsiv; + struct irq_data *irqd; + + if (!virq) + continue; + if (itype >= AEST_MAX_INTERRUPT_PER_NODE) + continue; + if (irq[itype] == virq) + continue; + irq[itype] = virq; + /* + * aest_config_irq() writes intr->gsiv directly + * to the hardware IRQ-config register, so it + * must hold the GIC hardware SPI number, not the + * Linux virtual IRQ. Convert here now that we + * have the virq in hand; the resource still gets + * the virq so devm_request_irq() works correctly. + */ + irqd = irq_get_irq_data(virq); + if (irqd) + intr->gsiv = irqd->hwirq; + + res[j].name = (itype == ACPI_AEST_NODE_FAULT_HANDLING) + ? AEST_FHI_NAME : AEST_ERI_NAME; + res[j].start = virq; + res[j].end = virq; + res[j].flags = IORESOURCE_IRQ; + j++; + } + } + } + + ret = platform_device_add_resources(pdev, res, j); + kfree(res); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = platform_device_add_data(pdev, &ahnode, sizeof(ahnode)); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int dt_aest_alloc_pdevs(struct dt_aest_priv *priv) +{ + struct aest_hnode *ahnode; + unsigned long i; + int ret = 0, index = 0; + + xa_for_each(&priv->aest_array, i, ahnode) { + struct platform_device *pdev = + dt_aest_alloc_pdev(ahnode, index++); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + pr_err("failed to alloc pdev for node %u: %d\n", + ahnode->id, ret); + break; + } + } + return ret; +} + +static int __init dt_aest_init(void) +{ + struct device_node *aest_root; + struct dt_aest_priv priv = {}; + int ret; + + if (!acpi_disabled) + return 0; + + aest_root = of_find_compatible_node(NULL, NULL, "arm,aest"); + if (!aest_root) + return 0; + + xa_init(&priv.aest_array); + + ret = dt_aest_init_nodes(aest_root, &priv); + of_node_put(aest_root); + if (ret) { + pr_err("failed to init AEST nodes: %d\n", ret); + return ret; + } + + ret = dt_aest_alloc_pdevs(&priv); + if (ret) { + pr_err("failed to alloc AEST pdevs: %d\n", ret); + return ret; + } + + pr_info("registered %u AEST error source(s) from DT\n", priv.node_id); + + return 0; +} +subsys_initcall_sync(dt_aest_init); From b5d57f2eed13abdc778d8a8d9478dc15eddc28b9 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:24 +0530 Subject: [PATCH 0374/1058] FROMLIST: arm64: dts: qcom: monaco: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-11-46e085bca4cc@oss.qualcomm.com Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/monaco.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bd..b97a143554422 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -742,6 +742,11 @@ #power-domain-cells = <0>; domain-idle-states = <&system_sleep>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { From 86d2225f9426c81032b19725bb4581b341898580 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Thu, 13 Nov 2025 18:35:19 +0530 Subject: [PATCH 0375/1058] FROMLIST: arm64: dts: qcom: monaco-evk: Enable Bluetooth support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a WCN6855 WiFi/Bluetooth module on an M.2 card. To make Bluetooth work, we need to define the necessary device tree nodes, including UART configuration and power supplies. Since there is no standard M.2 binding in the device tree at present, the PMU is described using dedicated PMU nodes to represent the internal regulators required by the module. The module provides a 3.3V supply, which originates from the main board’s 12V rail. To represent this power hierarchy in the device tree, add a fixed 12V regulator node as the DC-IN source and link it to the 3.3V regulator node. Link: https://lore.kernel.org/all/20251113130519.2647081-1-wei.deng@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 9d17ef7d2caf1..8da3428128baf 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -21,6 +21,7 @@ ethernet0 = ðernet0; i2c1 = &i2c1; serial0 = &uart7; + serial1 = &uart2; serial2 = &uart6; }; @@ -181,6 +182,86 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; + + vreg_dcin_12v: regulator-dcin-12v { + compatible = "regulator-fixed"; + + regulator-name = "VREG_DCIN_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + + regulator-boot-on; + regulator-always-on; + }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + vin-supply = <&vreg_dcin_12v>; + + regulator-boot-on; + }; + + wcn6855-pmu { + compatible = "qcom,wcn6855-pmu"; + + vddio-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddpmu-supply = <&vreg_wcn_3p3>; + vddpmumx-supply = <&vreg_wcn_3p3>; + vddpmucx-supply = <&vreg_wcn_3p3>; + vddrfa0p95-supply = <&vreg_wcn_3p3>; + vddrfa1p3-supply = <&vreg_wcn_3p3>; + vddrfa1p9-supply = <&vreg_wcn_3p3>; + vddpcielp3-supply = <&vreg_wcn_3p3>; + vddpcielp9-supply = <&vreg_wcn_3p3>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 { + regulator-name = "vreg_pmu_rfa_cmn"; + }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + }; + + vreg_pmu_wlcx_0p8: ldo2 { + regulator-name = "vreg_pmu_wlcx_0p8"; + }; + + vreg_pmu_wlmx_0p85: ldo3 { + regulator-name = "vreg_pmu_wlmx_0p85"; + }; + + vreg_pmu_btcmx_0p85: ldo4 { + regulator-name = "vreg_pmu_btcmx_0p85"; + }; + + vreg_pmu_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -862,6 +943,24 @@ }; }; +&uart2 { + status = "okay"; + + bluetooth: bluetooth { + compatible = "qcom,wcn6855-bt"; + max-speed = <3200000>; + + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + }; +}; + &uart6 { status = "okay"; }; From 4d0da9709e6c2de08d752114eb1c9d78a521dd4b Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 24 Nov 2025 14:55:20 +0530 Subject: [PATCH 0376/1058] FROMLIST: arm64: dts: qcom: monaco-evk: fix the SerDes PHY regulators The Qualcomm SerDes PHY, present on multiple boards, has two regulators providing supplies of 1.2V (L5A) and 0.9V (L4A). Update the node to reflect the same instead of incorrectly voting for only L4A. Link: https://lore.kernel.org/r/20251124-sgmiieth_serdes_regulator-v1-4-73ae8f9cbe2a@oss.qualcomm.com Fixes: 117d6bc9326b ("arm64: dts: qcom: qcs8300: Add Monaco EVK board") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 8da3428128baf..0eeb9154d5067 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -787,7 +787,8 @@ }; &serdes0 { - phy-supply = <&vreg_l4a>; + phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; status = "okay"; }; From 7875ddac25d8b570277aba3082b41b81aafaffcf Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 24 Nov 2025 14:55:21 +0530 Subject: [PATCH 0377/1058] FROMLIST: arm64: dts: qcom: qcs8300-ride: add additional SerDes PHY regulator Add the additional 0.9V regulator for the Qualcomm SerDes PHY. Link: https://lore.kernel.org/r/20251124-sgmiieth_serdes_regulator-v1-5-73ae8f9cbe2a@oss.qualcomm.com Fixes: 787cb3b4c434 ("arm64: dts: qcom: qcs8300-ride: enable ethernet0") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index e9a8553a8d821..2fffd4c01165d 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -703,6 +703,8 @@ &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; From 9abae761ac6d2ae51546642619a27559df0e7318 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 27 Nov 2025 17:28:29 +0530 Subject: [PATCH 0378/1058] QCLINUX: arch: arm64: qcom: qcs8300-ride: Enable PCIe Qref regulator PCIe phy needs to be voted for QREF regulator, As the base dtsi changes are still pending we haven't posted the actual fix. Till we post actual fix to upstream, use this change as a workaround. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index 2fffd4c01165d..4e00b1b9b562d 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -637,7 +637,7 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; status = "okay"; }; From 5474c0e458712a8372acdc39e76b5a16d6302842 Mon Sep 17 00:00:00 2001 From: Debraj Mukhopadhyay Date: Fri, 16 Jan 2026 17:40:04 +0530 Subject: [PATCH 0379/1058] mmc: Avoid reprogram all keys to Inline Crypto Engine for MMC runtime suspend resume Crypto reprogram all keys is called for each MMC runtime suspend/resume in current upstream design. If this is implemented as a non-interruptible call to TEE for security, the cpu core is blocked for execution while this call executes although the crypto engine already has the keys. For example, glitches in audio/video streaming applications have been observed due to this. Add the flag MMC_CAP2_CRYPTO_NO_REPROG as part of host->caps2 to control reprogramming keys to crypto engine for socs which dont require this feature. Link: https://lore.kernel.org/all/20260116121004.1829223-1-neeraj.soni@oss.qualcomm.com/ Signed-off-by: Seshu Madhavi Puppala Co-developed-by: Ram Prakash Gupta Signed-off-by: Ram Prakash Gupta Co-developed-by: Sarthak Garg Signed-off-by: Sarthak Garg Signed-off-by: Debraj Mukhopadhyay Signed-off-by: Neeraj Soni Acked-by: Adrian Hunter --- drivers/mmc/core/crypto.c | 2 +- drivers/mmc/host/sdhci-msm.c | 6 ++++++ include/linux/mmc/host.h | 5 +---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/crypto.c b/drivers/mmc/core/crypto.c index fec4fbf16a5b6..a5a90bfc634ee 100644 --- a/drivers/mmc/core/crypto.c +++ b/drivers/mmc/core/crypto.c @@ -15,7 +15,7 @@ void mmc_crypto_set_initial_state(struct mmc_host *host) { /* Reset might clear all keys, so reprogram all the keys. */ - if (host->caps2 & MMC_CAP2_CRYPTO) + if ((host->caps2 & MMC_CAP2_CRYPTO) && !(host->caps2 & MMC_CAP2_CRYPTO_NO_REPROG)) blk_crypto_reprogram_all_keys(&host->crypto_profile); } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0882ce74e0c9b..8be178059aa81 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1959,6 +1959,7 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, } mmc->caps2 |= MMC_CAP2_CRYPTO; + mmc->caps2 |= MMC_CAP2_CRYPTO_NO_REPROG; return 0; } @@ -2638,6 +2639,11 @@ static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) usleep_range(200, 210); reset_control_put(reset); +#ifdef CONFIG_MMC_CRYPTO + if (host->mmc->caps2 & MMC_CAP2_CRYPTO) + blk_crypto_reprogram_all_keys(&host->mmc->crypto_profile); +#endif + return ret; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ba84f02c2a101..83d92fb64417f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -457,12 +457,9 @@ struct mmc_host { #define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */ #define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */ #define MMC_CAP2_MERGE_CAPABLE (1 << 26) /* Host can merge a segment over the segment size */ -#ifdef CONFIG_MMC_CRYPTO #define MMC_CAP2_CRYPTO (1 << 27) /* Host supports inline encryption */ -#else -#define MMC_CAP2_CRYPTO 0 -#endif #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ +#define MMC_CAP2_CRYPTO_NO_REPROG (1 << 29) /* Host handles inline crypto key reprogramming */ bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */ bool uhs2_app_cmd; /* UHS-II flag for APP command */ From 697787951aa839a4cc983bb9879ccb43599782a1 Mon Sep 17 00:00:00 2001 From: Neeraj Soni Date: Tue, 10 Mar 2026 17:05:55 +0530 Subject: [PATCH 0380/1058] FROMLIST: dt-bindings: mmc: sdhci-msm: Add ICE phandle Starting with sc7280(kodiak), the ICE will have its own device-tree node. So add the qcom,ice property to reference it. To avoid double-modeling, when qcom,ice is present, disallow an embedded ICE register region in the SDHCI node. Older SoCs without ICE remain valid as no additional requirement is imposed. Co-developed-by: Abel Vesa Signed-off-by: Abel Vesa Co-developed-by: Abhinaba Rakshit Signed-off-by: Abhinaba Rakshit Signed-off-by: Neeraj Soni Link: https://lore.kernel.org/all/20260310113557.348502-2-neeraj.soni@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- .../bindings/mmc/qcom,sdhci-msm.yaml | 95 +++++++++++++------ 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml index bd558a11b7929..b3fcc1673c106 100644 --- a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml @@ -145,6 +145,11 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: platform specific settings for DLL_CONFIG reg. + qcom,ice: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to the Inline Crypto Engine (ICE) hardware block for this controller. + iommus: minItems: 1 maxItems: 8 @@ -198,35 +203,69 @@ allOf: enum: - qcom,sdhci-msm-v4 then: - properties: - reg: - minItems: 2 - items: - - description: Host controller register map - - description: SD Core register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 2 - items: - - const: hc - - const: core - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + else: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + - const: ice else: - properties: - reg: - minItems: 1 - items: - - description: Host controller register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 1 - items: - - const: hc - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + else: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + - const: ice unevaluatedProperties: false From 8edbec0b348bde7d37e7b501aef2c4e0f6b4f8fc Mon Sep 17 00:00:00 2001 From: Neeraj Soni Date: Tue, 10 Mar 2026 17:05:56 +0530 Subject: [PATCH 0381/1058] FROMLIST: arm64: dts: qcom: kodiak: enable the inline crypto engine for SDHC Add an ICE node to kodiak SoC description and enable it by adding a phandle to the SDHC node. Signed-off-by: Neeraj Soni Link: https://lore.kernel.org/all/20260310113557.348502-3-neeraj.soni@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..caf4ec9cf9fc6 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -1050,6 +1050,8 @@ qcom,dll-config = <0x0007642c>; qcom,ddr-config = <0x80040868>; + qcom,ice = <&sdhc_ice>; + mmc-ddr-1_8v; mmc-hs200-1_8v; mmc-hs400-1_8v; @@ -1076,6 +1078,13 @@ }; }; + sdhc_ice: crypto@7c8000 { + compatible = "qcom,sc7280-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x007c8000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>; + }; + gpi_dma0: dma-controller@900000 { #dma-cells = <3>; compatible = "qcom,sc7280-gpi-dma", "qcom,sm6350-gpi-dma"; From 2d49414e7269bce1fac5e2da275b25283d24a586 Mon Sep 17 00:00:00 2001 From: Neeraj Soni Date: Tue, 10 Mar 2026 17:05:57 +0530 Subject: [PATCH 0382/1058] FROMLIST: arm64: dts: qcom: monaco: enable the inline crypto engine for SDHC Add an ICE node to monaco SoC description and enable it by adding a phandle to the SDHC node. Signed-off-by: Neeraj Soni Link: https://lore.kernel.org/all/20260310113557.348502-4-neeraj.soni@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/monaco.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bd..95a888d584c1e 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4839,6 +4839,7 @@ mmc-hs200-1_8v; mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; + qcom,ice = <&sdhc_ice>; status = "disabled"; @@ -4867,6 +4868,13 @@ }; }; + sdhc_ice: crypto@87c8000 { + compatible = "qcom,qcs8300-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x087c8000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>; + }; + usb_1_hsphy: phy@8904000 { compatible = "qcom,qcs8300-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy"; From a653b1571fbfb71eca61a50000880a4affc80d6b Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Mon, 23 Mar 2026 14:47:54 +0530 Subject: [PATCH 0383/1058] dt-bindings: crypto: qcom,ice: Fix missing power-domain and iface clk The DT bindings for inline-crypto engine do not specify the UFS_PHY_GDSC power-domain and iface clock. Without enabling the iface clock and the associated power-domain the ICE hardware cannot function correctly and leads to unclocked hardware accesses being observed during probe. Fix the DT bindings for inline-crypto engine to require the UFS_PHY_GDSC power-domain and iface clock for new devices (Eliza and Milos) introduced in the current release (7.0) with yet-to-stabilize ABI, while preserving backward compatibility for older devices. Fixes: 618195a7ac3df ("dt-bindings: crypto: qcom,inline-crypto-engine: Document the Eliza ICE") Fixes: 85faec1e85555 ("dt-bindings: crypto: qcom,inline-crypto-engine: document the Milos ICE") Signed-off-by: Harshal Dev Reviewed-by: Krzysztof Kozlowski Reviewed-by: Kuldeep Singh Link: https://lore.kernel.org/r/20260323-qcom_ice_power_and_clk_vote-v4-1-e36044bbdfe9@oss.qualcomm.com --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index db895c50e2d25..92f462be35235 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -82,7 +82,7 @@ examples: compatible = "qcom,sm8550-inline-crypto-engine", "qcom,inline-crypto-engine"; reg = <0x01d88000 0x8000>; - clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, + clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; <&gcc GCC_UFS_PHY_AHB_CLK>; clock-names = "core", "iface"; From 3905b2feeb37b7246531b5db8067d6e40d7cc894 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Thu, 2 Apr 2026 00:05:09 +0530 Subject: [PATCH 0384/1058] arm64: dts: qcom: kodiak: Fix ICE reg size The ICE register region on Kodiak is currently defined as 0x8000 bytes. According to the hardware specification, the correct register size is 0x18000. Update the ICE node reg property to match the hardware. Fixes: dfd5ee7b34bb ("arm64: dts: qcom: sc7280: Add inline crypto engine") Signed-off-by: Kuldeep Singh Reviewed-by: Harshal Dev Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260402-ice_dt_reg_fix-v1-1-74e4c2129238@oss.qualcomm.com From 35732c3ccd881dc8a3d50ad09e12b9594efa0a9a Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Thu, 2 Apr 2026 00:05:10 +0530 Subject: [PATCH 0385/1058] arm64: dts: qcom: sm8450: Fix ICE reg size The ICE register region size was originally described incorrectly when the ICE hardware was first introduced. The same value was later carried over unchanged when the ICE node was split out from the UFS node into its own DT entry. Correct the register size to match the hardware specification. Fixes: 276ee34a40c1 ("arm64: dts: qcom: sm8450: add Inline Crypto Engine registers and clock") Signed-off-by: Kuldeep Singh Reviewed-by: Harshal Dev Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260402-ice_dt_reg_fix-v1-2-74e4c2129238@oss.qualcomm.com From 580c2482e267bea1ca100895951a60f09ef96e93 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 6 Apr 2026 21:13:20 +0530 Subject: [PATCH 0386/1058] arm64: dts: qcom: kodiak: Add iface clock and power domain for ice sdhc Qualcomm in-line crypto engine (ICE) platform driver specifies and votes for its own resources. Before accessing ICE hardware during probe, to avoid potential unclocked register access issues (when clk_ignore_unused is not passed on the kernel command line), in addition to the 'core' clock the 'iface' clock should also be turned on by the driver. This can only be done if power domain is enabled. Specify both power domain and the iface clock. Link: https://lore.kernel.org/linux-arm-msm/20260409-ice_emmc_clock_addition-v2-1-90bbcc057361@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index caf4ec9cf9fc6..ecf4790f3415c 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -1082,7 +1082,11 @@ compatible = "qcom,sc7280-inline-crypto-engine", "qcom,inline-crypto-engine"; reg = <0x0 0x007c8000 0x0 0x18000>; - clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmhpd SC7280_CX>; }; gpi_dma0: dma-controller@900000 { From beabac03036a596434bb02c3f91b7c9672ea7c15 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 6 Apr 2026 21:18:21 +0530 Subject: [PATCH 0387/1058] arm64: dts: qcom: monaco: Add iface clock and power domain for ice sdhc Qualcomm in-line crypto engine (ICE) platform driver specifies and votes for its own resources. Before accessing ICE hardware during probe, to avoid potential unclocked register access issues (when clk_ignore_unused is not passed on the kernel command line), in addition to the 'core' clock the 'iface' clock should also be turned on by the driver. This can only be done if power domain is enabled. Specify both power domain and the iface clock. Link: https://lore.kernel.org/linux-arm-msm/20260409-ice_emmc_clock_addition-v2-2-90bbcc057361@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/monaco.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 95a888d584c1e..09a883bd26449 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4872,7 +4872,11 @@ compatible = "qcom,qcs8300-inline-crypto-engine", "qcom,inline-crypto-engine"; reg = <0x0 0x087c8000 0x0 0x18000>; - clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmhpd RPMHPD_CX>; }; usb_1_hsphy: phy@8904000 { From ef8e7f32bccc433309cd1df44a9887a7ac1f2d7e Mon Sep 17 00:00:00 2001 From: Alok Tiwari Date: Sun, 8 Feb 2026 08:49:00 -0800 Subject: [PATCH 0388/1058] ntb_hw_amd: Fix incorrect debug message in link disable path amd_ntb_link_disable() prints "Enabling Link" which is misleading. Update the message to reflect that the link is being disabled. Signed-off-by: Alok Tiwari Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/amd/ntb_hw_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index 1a163596ddf54..df9150669ad3a 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -376,7 +376,7 @@ static int amd_ntb_link_disable(struct ntb_dev *ntb) if (ndev->ntb.topo == NTB_TOPO_SEC) return -EINVAL; - dev_dbg(&ntb->pdev->dev, "Enabling Link.\n"); + dev_dbg(&ntb->pdev->dev, "Disabling Link.\n"); return 0; } From dcf1125795923caff840d0c224c2aaa54f4e410c Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Wed, 4 Mar 2026 11:05:27 +0900 Subject: [PATCH 0389/1058] NTB: epf: Avoid pci_iounmap() with offset when PEER_SPAD and CONFIG share BAR When BAR_PEER_SPAD and BAR_CONFIG share one PCI BAR, the module teardown path ends up calling pci_iounmap() on the same iomem with some offset, which is unnecessary and triggers a kernel warning like the following: Trying to vunmap() nonexistent vm area (0000000069a5ffe8) WARNING: mm/vmalloc.c:3470 at vunmap+0x58/0x68, CPU#5: modprobe/2937 [...] Call trace: vunmap+0x58/0x68 (P) iounmap+0x34/0x48 pci_iounmap+0x2c/0x40 ntb_epf_pci_remove+0x44/0x80 [ntb_hw_epf] pci_device_remove+0x48/0xf8 device_remove+0x50/0x88 device_release_driver_internal+0x1c8/0x228 driver_detach+0x50/0xb0 bus_remove_driver+0x74/0x100 driver_unregister+0x34/0x68 pci_unregister_driver+0x34/0xa0 ntb_epf_pci_driver_exit+0x14/0xfe0 [ntb_hw_epf] [...] Fix it by unmapping only when PEER_SPAD and CONFIG use difference bars. Cc: stable@vger.kernel.org Fixes: e75d5ae8ab88 ("NTB: epf: Allow more flexibility in the memory BAR map method") Reviewed-by: Frank Li Signed-off-by: Koichiro Den Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/epf/ntb_hw_epf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c index af57554728429..c47607d4f8a7f 100644 --- a/drivers/ntb/hw/epf/ntb_hw_epf.c +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c @@ -729,7 +729,8 @@ static void ntb_epf_deinit_pci(struct ntb_epf_dev *ndev) struct pci_dev *pdev = ndev->ntb.pdev; pci_iounmap(pdev, ndev->ctrl_reg); - pci_iounmap(pdev, ndev->peer_spad_reg); + if (ndev->barno_map[BAR_PEER_SPAD] != ndev->barno_map[BAR_CONFIG]) + pci_iounmap(pdev, ndev->peer_spad_reg); pci_iounmap(pdev, ndev->db_reg); pci_release_regions(pdev); From a51f1fc66ec8aad75a9aa2cf20640d141b533721 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Mar 2026 22:14:15 -0700 Subject: [PATCH 0390/1058] NTB: fix kernel-doc warnings in ntb.h Correct a function name and function parameter name to avoid kernel-doc warnings: Warning: include/linux/ntb.h:575 expecting prototype for ntb_default_port_count(). Prototype was for ntb_default_peer_port_count() instead Warning: include/linux/ntb.h:590 function parameter 'pidx' not described in 'ntb_default_peer_port_number' Signed-off-by: Randy Dunlap Acked-by: Dave Jiang Signed-off-by: Jon Mason --- include/linux/ntb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ntb.h b/include/linux/ntb.h index 879c3e89e026f..ae72caa038597 100644 --- a/include/linux/ntb.h +++ b/include/linux/ntb.h @@ -567,7 +567,7 @@ void ntb_msg_event(struct ntb_dev *ntb); int ntb_default_port_number(struct ntb_dev *ntb); /** - * ntb_default_port_count() - get the default number of peer device ports + * ntb_default_peer_port_count() - get the default number of peer device ports * @ntb: NTB device context. * * By default hardware driver supports just one peer device. @@ -582,7 +582,7 @@ int ntb_default_peer_port_count(struct ntb_dev *ntb); /** * ntb_default_peer_port_number() - get the default peer port by given index * @ntb: NTB device context. - * @idx: Peer port index (should not differ from zero). + * @pidx: Peer port index (should not differ from zero). * * By default hardware driver supports just one peer device, so this method * shall return the corresponding value from enum ntb_default_port. From 9cebe6f6baef705b73810a107b99c7fcb7159f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Thu, 7 May 2026 09:41:01 +0200 Subject: [PATCH 0391/1058] ntb: amd: Use named initializer for pci_device_id::driver_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current list initialisation depends on the well hidden two zeros in the PCI_VDEVICE macro. Instead use a named initialisation that is more robust and easier to understand. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/amd/ntb_hw_amd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index df9150669ad3a..36bee0d8ac6cd 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -1328,15 +1328,15 @@ static const struct ntb_dev_data dev_data[] = { }; static const struct pci_device_id amd_ntb_pci_tbl[] = { - { PCI_VDEVICE(AMD, 0x145b), (kernel_ulong_t)&dev_data[0] }, - { PCI_VDEVICE(AMD, 0x148b), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x17d4), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x17d7), (kernel_ulong_t)&dev_data[2] }, - { PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] }, - { 0, } + { PCI_VDEVICE(AMD, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] }, + { PCI_VDEVICE(AMD, 0x148b), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x14c0), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x14c3), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x155a), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x17d4), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x17d7), .driver_data = (kernel_ulong_t)&dev_data[2] }, + { PCI_VDEVICE(HYGON, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] }, + { } }; MODULE_DEVICE_TABLE(pci, amd_ntb_pci_tbl); From 40b19af2ef1373e389f2e2645d668226abac421d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 Jun 2026 12:01:31 -0700 Subject: [PATCH 0392/1058] Linux 7.2-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 12fd3d2d47b58..b9c5792c79e01 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 7 -PATCHLEVEL = 1 +PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Baby Opossum Posse # *DOCUMENTATION* From d5785a4992833570a6ea60ec4a5c7282e6534fce Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 3 Feb 2026 15:46:32 +0800 Subject: [PATCH 0393/1058] FROMLIST: arm64: dts: qcom: sm8750: enable ETR and CTCU devices Embedded Trace Router(ETR) is working as a DDR memory sink to collect tracing data from source device and the CTCU device serves as the control unit for the ETR device. Link: https://lore.kernel.org/all/20260204-enable-ctcu-and-etr-v3-3-0bb95c590ae1@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 177 +++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index fafed417c66fc..20b483a73fa34 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -4106,6 +4106,35 @@ #reset-cells = <1>; }; + ctcu@10001000 { + compatible = "qcom,sm8750-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + stm@10002000 { compatible = "arm,coresight-stm", "arm,primecell"; reg = <0x0 0x10002000 0x0 0x1000>, @@ -4219,6 +4248,122 @@ }; }; + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x04e0 0x0>; + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0500 0x0>; + arm,scatter-gather; + arm,buffer-size = <0x400000>; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tpdm@10800000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x10800000 0x0 0x1000>; @@ -4889,6 +5034,38 @@ }; }; }; + + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&swao_rep_in>; + }; + }; + }; + }; + + replicator@10b06000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10b06000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + swao_rep_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + port { + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + }; }; tpda@10b08000 { From eef8defbf67bc47223ee2fa1ca4769048cd73e9f Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Mon, 23 Mar 2026 16:33:37 +0530 Subject: [PATCH 0394/1058] FROMLIST: arm64: dts: qcom: sm8750-mtp: Set sufficient voltage for panel nt37801 The NT37801 Sepc V1.0 chapter "5.7.1 Power On Sequence" states VDDI=1.65V~1.95V, so set sufficient voltage for panel nt37801. Signed-off-by: Ayushi Makhija Link: https://lore.kernel.org/all/20260323102229.1546504-1-quic_amakhija@quicinc.com/ Signed-off-by: Arpit Saini --- arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts index 3837f6785320d..6ba4e69bf377a 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts @@ -462,7 +462,7 @@ vreg_l12b_1p8: ldo12 { regulator-name = "vreg_l12b_1p8"; - regulator-min-microvolt = <1200000>; + regulator-min-microvolt = <1650000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = ; regulator-allow-set-load; From 734c20bb63e1db202b17b442bdc90315aaadaa66 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 4 May 2026 17:37:47 +0530 Subject: [PATCH 0395/1058] FROMLIST: arm64: dts: qcom: sm8750: wire UFS to ice instance The Inline Crypto Engine (ICE) exists as a standalone DT node, but the UFS node lacks the required qcom,ice phandle reference. Add the qcom,ice property to explicitly associate the UFS controller with its ICE instance. Fixes: d288abc3a70e ("arm64: dts: qcom: sm8750: Add UFS nodes for SM8750 SoC") Signed-off-by: Kuldeep Singh Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/lkml/20260429-sm8750_ice_dt_fix-v1-1-2540dc337082@oss.qualcomm.com/ Signed-off-by: Kumar Kartik --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 20b483a73fa34..154431fadd164 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -5622,6 +5622,7 @@ phy-names = "ufsphy"; #reset-cells = <1>; + qcom,ice = <&ice>; status = "disabled"; From a312ae92039b8d8be1b9d502be94f67a7538eece Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 29 May 2026 19:53:11 +0530 Subject: [PATCH 0396/1058] FROMLIST: arm64: dts: qcom: sm8750: add reboot-mode support Add PSCI SYSTEM_RESET2 reboot-modes for sm8750-mtp and sm8750-qrd for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Link: https://lore.kernel.org/r/20260529-psci_sys_reset-dt-changes-for-pakala-v2-1-1964ebf1924c@oss.qualcomm.com Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 7 +++++++ arch/arm64/boot/dts/qcom/sm8750-qrd.dts | 7 +++++++ arch/arm64/boot/dts/qcom/sm8750.dtsi | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts index 6ba4e69bf377a..4343ec5ca201c 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts @@ -1426,3 +1426,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts index 801c46d556022..795d0d34e47ef 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts @@ -1154,3 +1154,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 154431fadd164..be55e53fcea16 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -261,7 +261,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From 7f5c7fd3efbdd9566be86d27397ee527150d5aaf Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:50 -0700 Subject: [PATCH 0397/1058] FROMLIST: arm64: dts: qcom: sm8750: Add camss node Add node for the SM8750 camera subsystem. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-1-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 203 +++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index be55e53fcea16..2ac7d3cd47504 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3037,6 +3037,209 @@ #power-domain-cells = <1>; }; + camss: isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + + port@2 { + reg = <2>; + }; + + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; + }; + }; + + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,sm8750-mdss"; reg = <0x0 0x0ae00000 0x0 0x1000>; From 060d30a27761ed117774bfccd6238e5b8af28f82 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:51 -0700 Subject: [PATCH 0398/1058] FROMLIST: arm64: dts: qcom: sm8750: Add CCI definitions Qualcomm SM8750 SoC has three Camera Control Interface (CCI). Each controller contains two I2C hosts. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-2-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 282 +++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 2ac7d3cd47504..42f0e5c546394 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3037,6 +3037,96 @@ #power-domain-cells = <1>; }; + cci0: cci@ac7b000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac7c000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@ac7d000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camss: isp@ad27000 { compatible = "qcom,sm8750-camss"; @@ -3809,6 +3899,198 @@ gpio-ranges = <&tlmm 0 0 216>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio64", "gpio65"; From b2e5e9630f3ff8f681ae77aaab3ef852c4896df4 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:52 -0700 Subject: [PATCH 0399/1058] FROMLIST: arm64: dts: qcom: sm8750: Add camera MCLK pinctrl Define pinctrl definitions to enable camera master clocks on SM8750. Reviewed-by: Konrad Dybcio Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-3-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 42f0e5c546394..250d1a1818a26 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3899,6 +3899,62 @@ gpio-ranges = <&tlmm 0 0 216>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_aon_mclk2"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_aon_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { sda-pins { pins = "gpio113"; From e5183e91141567b40e818d014b5b545f2b515a6d Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Fri, 23 Jan 2026 15:18:28 +0530 Subject: [PATCH 0400/1058] FROMLIST: ufs: ufs-qcom: Fix sequential read variance The current devfreq downdifferential threshold of 5% causes overly aggressive frequency downscaling, leading to performance degradation sometimes during sequential read workloads. Update the UFS devfreq downdifferential threshold to 65. This widens the hysteresis window and prevents overly aggressive downscaling, ensuring that frequency is maintained for loads above 5% and scaling down occurs only when utilization falls below this level, while scale-up still triggers above the 70% threshold. Signed-off-by: Nitin Rawat Reviewed-by: Konrad Dybcio Signed-off-by: Pradeep P V K Link: https://lore.kernel.org/all/20260122141331.239354-4-nitin.rawat@oss.qualcomm.com/ --- drivers/ufs/host/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 291c434487648..6ccd162ab2ab0 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -2282,7 +2282,7 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, p->polling_ms = 60; p->timer = DEVFREQ_TIMER_DELAYED; d->upthreshold = 70; - d->downdifferential = 5; + d->downdifferential = 65; hba->clk_scaling.suspend_on_no_request = true; } From 6b862712451467650f1b56cfd3f4077d0553c488 Mon Sep 17 00:00:00 2001 From: Ram Prakash Gupta Date: Fri, 29 May 2026 13:40:45 +0530 Subject: [PATCH 0401/1058] FROMLIST: mmc: sdhci-msm: Set ice clk rate Set ice clk rate from sdhci msm platform driver, needed for target which are having legacy ice support, and need sdhci msm platform driver to set rate. Link: https://lore.kernel.org/all/20260529081045.2877910-2-ram.gupta@oss.qualcomm.com/ Signed-off-by: Ram Prakash Gupta Signed-off-by: Pradeep P V K --- drivers/mmc/host/sdhci-msm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0882ce74e0c9b..82611364cbc62 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -286,6 +286,7 @@ struct sdhci_msm_host { /* core, iface, cal and sleep clocks */ struct clk_bulk_data bulk_clks[4]; #ifdef CONFIG_MMC_CRYPTO + struct clk *ice_clk; /* ICE clock */ struct qcom_ice *ice; #endif unsigned long clk_rate; @@ -2703,6 +2704,17 @@ static int sdhci_msm_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_MMC_CRYPTO + /* Setup ICE clock */ + msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice"); + if (!IS_ERR(msm_host->ice_clk)) { + /* Vote for max. clk rate for max. performance */ + ret = clk_set_rate(msm_host->ice_clk, INT_MAX); + if (ret) + dev_err(&pdev->dev, "ice clk set rate failed (%d)\n", ret); + } +#endif + /* Setup main peripheral bus clock */ clk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(clk)) { From 77c70de6cb7508ed0fcd11154e26a1aa283fea2a Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:10 +0530 Subject: [PATCH 0402/1058] FROMLIST: scsi: ufs: core: Add UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk Add a new host quirk UFSHCD_QUIRK_SKIP_DEVICE_RESET to allow host controller drivers to skip asserting device reset during UFS power down. When RST_N is asserted, the UFS device firmware wakes up and executes its internal reset routine. This routine initializes multiple hardware blocks and causing the device to draw a large curreny during this time. If the power rail transitions to LPM (Low Power Mode) while the device is still drawing this elevated current, it may trigger an OCP (Over Current Protection) fault in the regulator. For some UFS devices (e.g., Micron), the elevated current draw persists until the reset line is deasserted, making a fixed delay insufficient to prevent OCP. This quirk allows such devices to skip device reset during UFS power down. The device reset will instead be asserted as part of the platform shutdown sequence. Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-2-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- include/ufs/ufshcd.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 248d0a5bef407..98ea715c03051 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -812,7 +812,22 @@ enum ufshcd_quirks { * (EQTR) using Adapt L0L1L2L3 length which is larger than what is * allowed by M-PHY spec ver 6.0. */ + UFSHCD_QUIRK_EXTENDED_TX_EQTR_ADAPT_LENGTH_L0L1L2L3 = 1 << 28, + /* + * Some UFS devices keep drawing larger current after reset is + * asserted until it is deasserted. Asserting device reset + * during UFS power down causes the device firmware to wake up and + * execute its reset routine, drawing current beyond the permissible + * limit for low-power mode (LPM). This may trigger an OCP fault on + * the regulator supplying power to UFS. + * + * Enable this quirk to skip asserting device reset during UFS power + * down. This is handled only in shutdown; the device reset will be + * asserted as part of the platform shutdown sequence. + */ + + UFSHCD_QUIRK_SKIP_DEVICE_RESET = 1 << 29, }; enum ufshcd_caps { From d86d915355ae0f4d79ec0223864f41cb1c30ab70 Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:11 +0530 Subject: [PATCH 0403/1058] FROMLIST: scsi: ufs: ufs-qcom: Enable SKIP DEVICE RESET Quirk A previous fix [1] addressed an OCP (Over Current Protection) issue during UFS power down (PC=3) by adding a 10ms delay after asserting HWRST. The delay allows the UFS device to complete its reset routine before the power rail transitions to LPM (Low Power Mode). However, this fix is insufficient for certain Micron UFS parts. Unlike other vendors whose reset routine completes within ~10ms, Micron parts continue to draw current beyond the LPM threshold for a longer duration after reset is asserted, specifically until the reset is deasserted (RST_N goes high). No fixed delay can reliably cover this window since there is currently no mechanism for the host to query whether the device reset routine has completed. Enable the UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk to skip device assert reset during UFS power down for Micron parts. For all other vendors, the existing behavior (assert reset + 10ms delay) is preserved. This quirk is applicable only during shutdown. The device reset will be asserted as part of the platform shutdown sequences. [1] commit 5127be409c6c ("scsi: ufs: ufs-qcom: Fix UFS OCP issue during UFS power down (PC=3)") Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-3-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- drivers/ufs/host/ufs-qcom.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 6ccd162ab2ab0..f605b3c73114b 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -770,9 +770,17 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, if (!ufs_qcom_is_link_active(hba)) ufs_qcom_disable_lane_clks(host); - - /* reset the connected UFS device during power down */ - if (ufs_qcom_is_link_off(hba) && host->device_reset) { + /* + * For some UFS vendors, skip asserting device reset here. + * These vendor parts keep drawing larger current after reset + * is asserted until it is deasserted, and the 10ms delay is + * not sufficient to prevent OCP (Over Current Protection) + * on the regulator. This is for the powerdown case, so + * the device reset can be asserted later as part of the + * platform shutdown sequence. + */ + if (ufs_qcom_is_link_off(hba) && host->device_reset && + !(hba->quirks & UFSHCD_QUIRK_SKIP_DEVICE_RESET)) { ufs_qcom_device_reset_ctrl(hba, true); /* * After sending the SSU command, asserting the rst_n @@ -1288,6 +1296,19 @@ static struct ufs_dev_quirk ufs_qcom_dev_fixups[] = { static void ufs_qcom_fixup_dev_quirks(struct ufs_hba *hba) { ufshcd_fixup_dev_quirks(hba, ufs_qcom_dev_fixups); + + /* + * Some UFS parts keep drawing larger current after reset is asserted + * until it is deasserted. The 10ms delay added after asserting HWRST + * (as done for other vendors) is not sufficient for these parts. + * + * Skip asserting device reset during UFS power down for these parts + * to prevent OCP (Over Current Protection) fault on the regulator. + * This is handled only in shutdown; the device reset will be asserted + * as part of the platform shutdown sequence. + */ + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_MICRON) + hba->quirks |= UFSHCD_QUIRK_SKIP_DEVICE_RESET; } static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) From 20d54e3cfd8f864dd8fb4d27451f456914634086 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Fri, 13 Mar 2026 15:53:53 +0530 Subject: [PATCH 0404/1058] FROMLIST: iommu/arm-smmu: Use pm_runtime in fault handlers Commit d4a44f0750bb ("iommu/arm-smmu: Invoke pm_runtime across the driver") enabled pm_runtime for the arm-smmu device. On systems where the SMMU sits in a power domain, all register accesses must be done while the device is runtime active to avoid unclocked register reads and potential NoC errors. So far, this has not been an issue for most SMMU clients because stall-on-fault is enabled by default. While a translation fault is being handled, the SMMU stalls further translations for that context bank, so the fault handler would not race with a powered-down SMMU. Adreno SMMU now disables stall-on-fault in the presence of fault storms to avoid saturating SMMU resources and hanging the GMU. With stall-on-fault disabled, the SMMU can generate faults while its power domain may no longer be enabled, which makes unclocked accesses to fault-status registers in the SMMU fault handlers possible. Guard the context and global fault handlers with pm_runtime_get_if_active() and pm_runtime_put_autosuspend() so that all SMMU fault register accesses are done with the SMMU powered. In case pm_runtime is not active we can safely ignore the fault as for pm runtime resume the smmu device is reset and fault registers are cleared. List: https://lore.kernel.org/all/20260313-smmu-rpm-v2-1-8c2236b402b0@oss.qualcomm.com/ Fixes: b13044092c1e ("drm/msm: Temporarily disable stall-on-fault after a page fault") Co-developed-by: Pratyush Brahma Signed-off-by: Pratyush Brahma Signed-off-by: Prakash Gupta --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 60 +++++++++++++++++---------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 0bd21d206eb3e..83a6fac172ae9 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -462,10 +462,20 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) int idx = smmu_domain->cfg.cbndx; int ret; + if (!pm_runtime_get_if_active(smmu->dev)) + return IRQ_NONE; + + if (smmu->impl && smmu->impl->context_fault) { + ret = smmu->impl->context_fault(irq, dev); + goto out_power_off; + } + arm_smmu_read_context_fault_info(smmu, idx, &cfi); - if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT)) - return IRQ_NONE; + if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT)) { + ret = IRQ_NONE; + goto out_power_off; + } ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova, cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ); @@ -480,7 +490,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) ret == -EAGAIN ? 0 : ARM_SMMU_RESUME_TERMINATE); } - return IRQ_HANDLED; + ret = IRQ_HANDLED; + +out_power_off: + pm_runtime_put_autosuspend(smmu->dev); + + return ret; } static irqreturn_t arm_smmu_global_fault(int irq, void *dev) @@ -489,14 +504,25 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) struct arm_smmu_device *smmu = dev; static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); + int ret; + + if (!pm_runtime_get_if_active(smmu->dev)) + return IRQ_NONE; + + if (smmu->impl && smmu->impl->global_fault) { + ret = smmu->impl->global_fault(irq, dev); + goto out_power_off; + } gfsr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSR); gfsynr0 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR0); gfsynr1 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR1); gfsynr2 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR2); - if (!gfsr) - return IRQ_NONE; + if (!gfsr) { + ret = IRQ_NONE; + goto out_power_off; + } if (__ratelimit(&rs)) { if (IS_ENABLED(CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT) && @@ -513,7 +539,11 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) } arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sGFSR, gfsr); - return IRQ_HANDLED; + ret = IRQ_HANDLED; + +out_power_off: + pm_runtime_put_autosuspend(smmu->dev); + return ret; } static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, @@ -683,7 +713,6 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain, enum io_pgtable_fmt fmt; struct iommu_domain *domain = &smmu_domain->domain; struct arm_smmu_cfg *cfg = &smmu_domain->cfg; - irqreturn_t (*context_fault)(int irq, void *dev); mutex_lock(&smmu_domain->init_mutex); if (smmu_domain->smmu) @@ -850,19 +879,14 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain, */ irq = smmu->irqs[cfg->irptndx]; - if (smmu->impl && smmu->impl->context_fault) - context_fault = smmu->impl->context_fault; - else - context_fault = arm_smmu_context_fault; - if (smmu->impl && smmu->impl->context_fault_needs_threaded_irq) ret = devm_request_threaded_irq(smmu->dev, irq, NULL, - context_fault, + arm_smmu_context_fault, IRQF_ONESHOT | IRQF_SHARED, "arm-smmu-context-fault", smmu_domain); else - ret = devm_request_irq(smmu->dev, irq, context_fault, IRQF_SHARED, + ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault, IRQF_SHARED, "arm-smmu-context-fault", smmu_domain); if (ret < 0) { @@ -2125,7 +2149,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int num_irqs, i, err; u32 global_irqs, pmu_irqs; - irqreturn_t (*global_fault)(int irq, void *dev); smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); if (!smmu) { @@ -2205,18 +2228,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->num_context_irqs = smmu->num_context_banks; } - if (smmu->impl && smmu->impl->global_fault) - global_fault = smmu->impl->global_fault; - else - global_fault = arm_smmu_global_fault; - for (i = 0; i < global_irqs; i++) { int irq = platform_get_irq(pdev, i); if (irq < 0) return irq; - err = devm_request_irq(dev, irq, global_fault, IRQF_SHARED, + err = devm_request_irq(dev, irq, arm_smmu_global_fault, IRQF_SHARED, "arm-smmu global fault", smmu); if (err) return dev_err_probe(dev, err, From 5407fde1648c950a333c13be78ff62021bfcff4a Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:02 +0530 Subject: [PATCH 0405/1058] FROMLIST: dt-bindings: iommu: arm,smmu: Document interconnects property Some SoC implementations require a bandwidth vote on an interconnect path before the SMMU register space is accessible. Add the optional 'interconnects' property to the binding to allow platform DT nodes to describe this path. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-0-2a6d8ca30d63@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bibek Kumar Patro --- .../devicetree/bindings/iommu/arm,smmu.yaml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index a701dec2fa0a4..fab8944d7b634 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -246,6 +246,13 @@ properties: minItems: 1 maxItems: 3 + interconnects: + maxItems: 1 + description: + Interconnect path to the SMMU register space. Required on SoCs + where the SMMU registers are only accessible after a bandwidth + vote has been placed on the interconnect fabric. + nvidia,memory-controller: description: | A phandle to the memory controller on NVIDIA Tegra186 and later SoCs. @@ -644,6 +651,26 @@ allOf: clock-names: false clocks: false + - if: + properties: + compatible: + items: + - enum: + - qcom,qcs615-smmu-500 + - qcom,qcs8300-smmu-500 + - qcom,sa8775p-smmu-500 + - qcom,sc7280-smmu-500 + - const: qcom,adreno-smmu + - const: qcom,smmu-500 + - const: arm,mmu-500 + then: + properties: + interconnects: + maxItems: 1 + else: + properties: + interconnects: false + - if: properties: compatible: From ee3de84ce85c3144f4bdbfcdd9082824e6a00fbc Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Thu, 2 Apr 2026 11:45:43 +0530 Subject: [PATCH 0406/1058] FROMLIST: dt-bindings: clock: qcom: Add Glymur camera clock controller Add device tree bindings for the camera clock controller on Qualcomm Glymur SoC. Signed-off-by: Jagadeesh Kona Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260402-glymur_camcc-v1-1-e8da05a21da7@oss.qualcomm.com --- .../bindings/clock/qcom,x1e80100-camcc.yaml | 3 + include/dt-bindings/clock/qcom,glymur-camcc.h | 122 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,glymur-camcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml index b28614186cc09..e7cb8cfa957a4 100644 --- a/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml @@ -8,12 +8,14 @@ title: Qualcomm Camera Clock & Reset Controller on x1e80100 maintainers: - Bryan O'Donoghue + - Jagadeesh Kona description: | Qualcomm camera clock control module provides the clocks, resets and power domains on x1e80100. See also: + include/dt-bindings/clock/qcom,glymur-camcc.h include/dt-bindings/clock/qcom,x1e80100-camcc.h allOf: @@ -22,6 +24,7 @@ allOf: properties: compatible: enum: + - qcom,glymur-camcc - qcom,x1e80100-camcc - qcom,x1p42100-camcc diff --git a/include/dt-bindings/clock/qcom,glymur-camcc.h b/include/dt-bindings/clock/qcom,glymur-camcc.h new file mode 100644 index 0000000000000..0c93fc77ef268 --- /dev/null +++ b/include/dt-bindings/clock/qcom,glymur-camcc.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_GLYMUR_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_GLYMUR_H + +/* CAM_CC clocks */ +#define CAM_CC_BPS_AHB_CLK 0 +#define CAM_CC_BPS_CLK 1 +#define CAM_CC_BPS_CLK_SRC 2 +#define CAM_CC_BPS_FAST_AHB_CLK 3 +#define CAM_CC_CAMNOC_AXI_NRT_CLK 4 +#define CAM_CC_CAMNOC_AXI_RT_CLK 5 +#define CAM_CC_CAMNOC_AXI_RT_CLK_SRC 6 +#define CAM_CC_CAMNOC_DCD_XO_CLK 7 +#define CAM_CC_CAMNOC_XO_CLK 8 +#define CAM_CC_CCI_0_CLK 9 +#define CAM_CC_CCI_0_CLK_SRC 10 +#define CAM_CC_CCI_1_CLK 11 +#define CAM_CC_CCI_1_CLK_SRC 12 +#define CAM_CC_CORE_AHB_CLK 13 +#define CAM_CC_CPAS_AHB_CLK 14 +#define CAM_CC_CPAS_BPS_CLK 15 +#define CAM_CC_CPAS_FAST_AHB_CLK 16 +#define CAM_CC_CPAS_IFE_0_CLK 17 +#define CAM_CC_CPAS_IFE_1_CLK 18 +#define CAM_CC_CPAS_IFE_LITE_CLK 19 +#define CAM_CC_CPAS_IPE_NPS_CLK 20 +#define CAM_CC_CPHY_RX_CLK_SRC 21 +#define CAM_CC_CSI0PHYTIMER_CLK 22 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 23 +#define CAM_CC_CSI1PHYTIMER_CLK 24 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 25 +#define CAM_CC_CSI4PHYTIMER_CLK 26 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 27 +#define CAM_CC_CSID_CLK 28 +#define CAM_CC_CSID_CLK_SRC 29 +#define CAM_CC_CSID_CSIPHY_RX_CLK 30 +#define CAM_CC_CSIPHY0_CLK 31 +#define CAM_CC_CSIPHY1_CLK 32 +#define CAM_CC_CSIPHY4_CLK 33 +#define CAM_CC_FAST_AHB_CLK_SRC 34 +#define CAM_CC_GDSC_CLK 35 +#define CAM_CC_ICP_AHB_CLK 36 +#define CAM_CC_ICP_CLK 37 +#define CAM_CC_ICP_CLK_SRC 38 +#define CAM_CC_IFE_0_CLK 39 +#define CAM_CC_IFE_0_CLK_SRC 40 +#define CAM_CC_IFE_0_DSP_CLK 41 +#define CAM_CC_IFE_0_FAST_AHB_CLK 42 +#define CAM_CC_IFE_1_CLK 43 +#define CAM_CC_IFE_1_CLK_SRC 44 +#define CAM_CC_IFE_1_DSP_CLK 45 +#define CAM_CC_IFE_1_FAST_AHB_CLK 46 +#define CAM_CC_IFE_LITE_AHB_CLK 47 +#define CAM_CC_IFE_LITE_CLK 48 +#define CAM_CC_IFE_LITE_CLK_SRC 49 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 50 +#define CAM_CC_IFE_LITE_CSID_CLK 51 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 52 +#define CAM_CC_IPE_NPS_AHB_CLK 53 +#define CAM_CC_IPE_NPS_CLK 54 +#define CAM_CC_IPE_NPS_CLK_SRC 55 +#define CAM_CC_IPE_NPS_FAST_AHB_CLK 56 +#define CAM_CC_IPE_PPS_CLK 57 +#define CAM_CC_IPE_PPS_FAST_AHB_CLK 58 +#define CAM_CC_JPEG_CLK 59 +#define CAM_CC_JPEG_CLK_SRC 60 +#define CAM_CC_MCLK0_CLK 61 +#define CAM_CC_MCLK0_CLK_SRC 62 +#define CAM_CC_MCLK1_CLK 63 +#define CAM_CC_MCLK1_CLK_SRC 64 +#define CAM_CC_MCLK2_CLK 65 +#define CAM_CC_MCLK2_CLK_SRC 66 +#define CAM_CC_MCLK3_CLK 67 +#define CAM_CC_MCLK3_CLK_SRC 68 +#define CAM_CC_MCLK4_CLK 69 +#define CAM_CC_MCLK4_CLK_SRC 70 +#define CAM_CC_MCLK5_CLK 71 +#define CAM_CC_MCLK5_CLK_SRC 72 +#define CAM_CC_MCLK6_CLK 73 +#define CAM_CC_MCLK6_CLK_SRC 74 +#define CAM_CC_MCLK7_CLK 75 +#define CAM_CC_MCLK7_CLK_SRC 76 +#define CAM_CC_PLL0 77 +#define CAM_CC_PLL0_OUT_EVEN 78 +#define CAM_CC_PLL0_OUT_ODD 79 +#define CAM_CC_PLL1 80 +#define CAM_CC_PLL1_OUT_EVEN 81 +#define CAM_CC_PLL2 82 +#define CAM_CC_PLL3 83 +#define CAM_CC_PLL3_OUT_EVEN 84 +#define CAM_CC_PLL4 85 +#define CAM_CC_PLL4_OUT_EVEN 86 +#define CAM_CC_PLL5 87 +#define CAM_CC_PLL5_OUT_EVEN 88 +#define CAM_CC_QDSS_DEBUG_CLK 89 +#define CAM_CC_QDSS_DEBUG_CLK_SRC 90 +#define CAM_CC_QDSS_DEBUG_XO_CLK 91 +#define CAM_CC_SLEEP_CLK 92 +#define CAM_CC_SLEEP_CLK_SRC 93 +#define CAM_CC_SLOW_AHB_CLK_SRC 94 +#define CAM_CC_XO_CLK_SRC 95 + +/* CAM_CC power domains */ +#define CAM_CC_BPS_GDSC 0 +#define CAM_CC_IFE_0_GDSC 1 +#define CAM_CC_IFE_1_GDSC 2 +#define CAM_CC_IPE_0_GDSC 3 +#define CAM_CC_TITAN_TOP_GDSC 4 + +/* CAM_CC resets */ +#define CAM_CC_BPS_BCR 0 +#define CAM_CC_ICP_BCR 1 +#define CAM_CC_IFE_0_BCR 2 +#define CAM_CC_IFE_1_BCR 3 +#define CAM_CC_IPE_0_BCR 4 +#define CAM_CC_QDSS_DEBUG_BCR 5 + +#endif From b5005b941919a68b00b6a9d8d87c94ec1e4a3dca Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Mon, 6 Apr 2026 14:50:04 +0530 Subject: [PATCH 0407/1058] FROMLIST: clk: qcom: camcc-glymur: Add camera clock controller driver Add support for the camera clock controller for camera clients to be able to request for camcc clocks on Glymur platform. Signed-off-by: Jagadeesh Kona Link: https://lore.kernel.org/r/20260402-glymur_camcc-v1-2-e8da05a21da7@oss.qualcomm.com --- drivers/clk/qcom/Kconfig | 10 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/camcc-glymur.c | 2280 +++++++++++++++++++++++++++++++ 3 files changed, 2291 insertions(+) create mode 100644 drivers/clk/qcom/camcc-glymur.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 7d84c2f1d911a..fae9476910067 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -45,6 +45,16 @@ config CLK_ELIZA_TCSRCC Support for the TCSR clock controller on Eliza devices. Say Y if you want to use peripheral devices such as USB/PCIe/UFS. +config CLK_GLYMUR_CAMCC + tristate "Glymur Camera Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_GLYMUR_GCC + help + Support for the camera clock controller on Qualcomm Technologies, Inc + Glymur devices. + Say Y if you want to support camera devices and functionality such as + capturing pictures. + config CLK_GLYMUR_DISPCC tristate "Glymur Display Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 58f9a5eb6fd7f..042ebd64448fe 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o +obj-$(CONFIG_CLK_GLYMUR_CAMCC) += camcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GCC) += gcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GPUCC) += gpucc-glymur.o gxclkctl-kaanapali.o diff --git a/drivers/clk/qcom/camcc-glymur.c b/drivers/clk/qcom/camcc-glymur.c new file mode 100644 index 0000000000000..b21e6830a72b4 --- /dev/null +++ b/drivers/clk/qcom/camcc-glymur.c @@ -0,0 +1,2280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_IFACE, + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_BI_TCXO_AO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EVEN, + P_CAM_CC_PLL2_OUT_MAIN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_CAM_CC_PLL5_OUT_EVEN, + P_SLEEP_CLK, +}; + +static const struct pll_vco rivian_eko_t_vco[] = { + { 883200000, 1171200000, 0 }, +}; + +static const struct pll_vco taycan_eko_t_vco[] = { + { 249600000, 2500000000, 0 }, +}; + +/* 1200.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .alpha = 0x8000, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00008408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .config = &cam_cc_pll0_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 608.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x1f, + .alpha = 0xaaaa, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .config = &cam_cc_pll1_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x12000000, + .config_ctl_hi_val = 0x00890263, + .config_ctl_hi1_val = 0x1af04237, + .config_ctl_hi2_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .config = &cam_cc_pll2_config, + .vco_table = rivian_eko_t_vco, + .num_vco = ARRAY_SIZE(rivian_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_rivian_eko_t_ops, + }, + }, +}; + +/* 691.2 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x24, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .config = &cam_cc_pll3_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 691.2 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x24, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .config = &cam_cc_pll4_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll5_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll5 = { + .offset = 0x5000, + .config = &cam_cc_pll5_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = { + .offset = 0x5000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll5_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll5.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL5_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll5_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EVEN, 3 }, + { P_CAM_CC_PLL2_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll2.clkr.hw }, + { .hw = &cam_cc_pll2.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map cam_cc_parent_map_6_ao[] = { + { P_BI_TCXO_AO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6_ao[] = { + { .index = DT_BI_TCXO_AO }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(160000000, P_CAM_CC_PLL0_OUT_ODD, 2.5, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x10278, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_axi_rt_clk_src[] = { + F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_axi_rt_clk_src = { + .cmd_rcgr = 0x137b4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_axi_rt_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_rt_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(30000000, P_CAM_CC_PLL5_OUT_EVEN, 16, 0, 0), + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0x1350c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0x1363c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x11168, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(266666667, P_CAM_CC_PLL0_OUT_ODD, 1.5, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x150e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x15104, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x15124, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csid_clk_src = { + .cmd_rcgr = 0x1378c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x10018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0x133cc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(345600000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(727000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0x11018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = { + F(345600000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(432000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(727000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0x12018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_1_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_lite_clk_src[] = { + F(266666667, P_CAM_CC_PLL0_OUT_ODD, 1.5, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0x13000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0x13140, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = { + F(304000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(364000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(500000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(700000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_nps_clk_src = { + .cmd_rcgr = 0x103d0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = { + F(160000000, P_CAM_CC_PLL0_OUT_ODD, 2.5, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0x13284, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_jpeg_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_CC_PLL2_OUT_MAIN, 10, 1, 4), + F(68571429, P_CAM_CC_PLL2_OUT_MAIN, 14, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x15000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk0_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x1501c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk1_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x15038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk2_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x15054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk3_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x15070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk4_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .cmd_rcgr = 0x1508c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk5_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk6_clk_src = { + .cmd_rcgr = 0x150a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk6_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk7_clk_src = { + .cmd_rcgr = 0x150c4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = { + F(60000000, P_CAM_CC_PLL5_OUT_EVEN, 8, 0, 0), + F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0), + F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_qdss_debug_clk_src = { + .cmd_rcgr = 0x137fc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0x13964, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(64000000, P_CAM_CC_PLL5_OUT_EVEN, 7.5, 0, 0), + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x10148, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0x13948, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6_ao, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_6_ao, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x10274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10274, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_clk = { + .halt_reg = 0x103a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_bps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_fast_ahb_clk = { + .halt_reg = 0x10144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_nrt_clk = { + .halt_reg = 0x137e0, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x137e0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x137e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_nrt_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_axi_rt_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_rt_clk = { + .halt_reg = 0x137cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_rt_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_axi_rt_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0x137f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137f0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_xo_clk = { + .halt_reg = 0x137f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0x13638, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13638, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0x13768, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13768, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0x13944, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x13944, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ahb_clk = { + .halt_reg = 0x1376c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1376c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_bps_clk = { + .halt_reg = 0x103b4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103b4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_bps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_bps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_fast_ahb_clk = { + .halt_reg = 0x1377c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1377c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_0_clk = { + .halt_reg = 0x11154, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11154, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_1_clk = { + .halt_reg = 0x12040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_lite_clk = { + .halt_reg = 0x1313c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1313c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ipe_nps_clk = { + .halt_reg = 0x1050c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1050c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x150f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x1511c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1511c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x15250, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15250, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi4phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_clk = { + .halt_reg = 0x137a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_csiphy_rx_clk = { + .halt_reg = 0x15100, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15100, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_csiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x150fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x15120, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15120, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x15254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_ahb_clk = { + .halt_reg = 0x13508, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13508, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_clk = { + .halt_reg = 0x134f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x134f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_clk = { + .halt_reg = 0x11144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_dsp_clk = { + .halt_reg = 0x11158, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11158, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_fast_ahb_clk = { + .halt_reg = 0x11164, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11164, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_clk = { + .halt_reg = 0x12030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_dsp_clk = { + .halt_reg = 0x12044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_fast_ahb_clk = { + .halt_reg = 0x12050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0x13280, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13280, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0x1312c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1312c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0x1327c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1327c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0x1326c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1326c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_ahb_clk = { + .halt_reg = 0x10528, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10528, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_clk = { + .halt_reg = 0x104fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x104fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = { + .halt_reg = 0x1052c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1052c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_clk = { + .halt_reg = 0x10510, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10510, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = { + .halt_reg = 0x10530, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10530, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_clk = { + .halt_reg = 0x133b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x133b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk0_clk = { + .halt_reg = 0x15018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk1_clk = { + .halt_reg = 0x15034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk2_clk = { + .halt_reg = 0x15050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk3_clk = { + .halt_reg = 0x1506c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1506c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk4_clk = { + .halt_reg = 0x15088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk5_clk = { + .halt_reg = 0x150a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk6_clk = { + .halt_reg = 0x150c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk7_clk = { + .halt_reg = 0x150dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_clk = { + .halt_reg = 0x13928, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13928, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_qdss_debug_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_xo_clk = { + .halt_reg = 0x1392c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1392c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc cam_cc_titan_top_gdsc = { + .gdscr = 0x13930, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_bps_gdsc = { + .gdscr = 0x10004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_bps_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_0_gdsc = { + .gdscr = 0x11004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_1_gdsc = { + .gdscr = 0x12004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ipe_0_gdsc = { + .gdscr = 0x103bc, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ipe_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *cam_cc_glymur_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.clkr, + [CAM_CC_CAMNOC_AXI_NRT_CLK] = &cam_cc_camnoc_axi_nrt_clk.clkr, + [CAM_CC_CAMNOC_AXI_RT_CLK] = &cam_cc_camnoc_axi_rt_clk.clkr, + [CAM_CC_CAMNOC_AXI_RT_CLK_SRC] = &cam_cc_camnoc_axi_rt_clk_src.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr, + [CAM_CC_CPAS_BPS_CLK] = &cam_cc_cpas_bps_clk.clkr, + [CAM_CC_CPAS_FAST_AHB_CLK] = &cam_cc_cpas_fast_ahb_clk.clkr, + [CAM_CC_CPAS_IFE_0_CLK] = &cam_cc_cpas_ife_0_clk.clkr, + [CAM_CC_CPAS_IFE_1_CLK] = &cam_cc_cpas_ife_1_clk.clkr, + [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr, + [CAM_CC_CPAS_IPE_NPS_CLK] = &cam_cc_cpas_ipe_nps_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr, + [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr, + [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, + [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, + [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, + [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_0_FAST_AHB_CLK] = &cam_cc_ife_0_fast_ahb_clk.clkr, + [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr, + [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr, + [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_1_FAST_AHB_CLK] = &cam_cc_ife_1_fast_ahb_clk.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr, + [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr, + [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr, + [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr, + [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr, + [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr, + [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr, + [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr, + [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr, + [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr, + [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr, + [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr, + [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr, + [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr, + [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr, + [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr, + [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr, + [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr, + [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr, + [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr, + [CAM_CC_MCLK7_CLK] = &cam_cc_mclk7_clk.clkr, + [CAM_CC_MCLK7_CLK_SRC] = &cam_cc_mclk7_clk_src.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_PLL5] = &cam_cc_pll5.clkr, + [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr, + [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr, + [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr, + [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_glymur_gdscs[] = { + [CAM_CC_BPS_GDSC] = &cam_cc_bps_gdsc, + [CAM_CC_IFE_0_GDSC] = &cam_cc_ife_0_gdsc, + [CAM_CC_IFE_1_GDSC] = &cam_cc_ife_1_gdsc, + [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc, + [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_glymur_resets[] = { + [CAM_CC_BPS_BCR] = { 0x10000 }, + [CAM_CC_ICP_BCR] = { 0x133c8 }, + [CAM_CC_IFE_0_BCR] = { 0x11000 }, + [CAM_CC_IFE_1_BCR] = { 0x12000 }, + [CAM_CC_IPE_0_BCR] = { 0x103b8 }, + [CAM_CC_QDSS_DEBUG_BCR] = { 0x137f8 }, +}; + +static struct clk_alpha_pll *cam_cc_glymur_plls[] = { + &cam_cc_pll0, + &cam_cc_pll1, + &cam_cc_pll2, + &cam_cc_pll3, + &cam_cc_pll4, + &cam_cc_pll5, +}; + +static u32 cam_cc_glymur_critical_cbcrs[] = { + 0x13960, /* CAM_CC_GDSC_CLK */ + 0x1397c, /* CAM_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_cc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1603c, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_cc_glymur_driver_data = { + .alpha_plls = cam_cc_glymur_plls, + .num_alpha_plls = ARRAY_SIZE(cam_cc_glymur_plls), + .clk_cbcrs = cam_cc_glymur_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_cc_glymur_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_cc_glymur_desc = { + .config = &cam_cc_glymur_regmap_config, + .clks = cam_cc_glymur_clocks, + .num_clks = ARRAY_SIZE(cam_cc_glymur_clocks), + .resets = cam_cc_glymur_resets, + .num_resets = ARRAY_SIZE(cam_cc_glymur_resets), + .gdscs = cam_cc_glymur_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_glymur_gdscs), + .use_rpm = true, + .driver_data = &cam_cc_glymur_driver_data, +}; + +static const struct of_device_id cam_cc_glymur_match_table[] = { + { .compatible = "qcom,glymur-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_glymur_match_table); + +static int cam_cc_glymur_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_cc_glymur_desc); +} + +static struct platform_driver cam_cc_glymur_driver = { + .probe = cam_cc_glymur_probe, + .driver = { + .name = "camcc-glymur", + .of_match_table = cam_cc_glymur_match_table, + }, +}; + +module_platform_driver(cam_cc_glymur_driver); + +MODULE_DESCRIPTION("QTI CAMCC GLYMUR Driver"); +MODULE_LICENSE("GPL"); From 948a60545123b38af40f0fe283a0271cae5d2f62 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Mon, 27 Apr 2026 12:08:55 +0530 Subject: [PATCH 0408/1058] FROMLIST: clk: qcom: gdsc: Add custom disable callback for GX GDSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GX GDSC is a special power domain that should only be disabled by OS during GMU recovery. In all other scenarios, the GMU firmware is responsible for handling its disable sequence, and OS must not interfere. During the resume_noirq() phase of system resume, the GenPD framework enables all power domains and later disables them in the complete() phase if there are no active votes from OS. This behavior can incorrectly disable the GX GDSC while the GMU firmware is still using it. To prevent this, implement a custom disable callback for GX GDSC that relies on GenPD’s synced_poweroff flag. The GMU driver sets this flag only during recovery, allowing OS to explicitly disable GX GDSC in hardware in that case. In all other situations, the disable callback will avoid touching GX GDSC hardware. Signed-off-by: Jagadeesh Kona Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260427-gfx-clk-fixes-v2-1-797e54b3d464@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/gdsc.c | 22 ++++++++++++++++++++++ drivers/clk/qcom/gdsc.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index ee5f86ca50cb7..f419a28f616b6 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -708,3 +708,25 @@ int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain) return ret; } EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable); + +/* + * GX GDSC is a special power domain. Normally, its disable sequence + * is managed by the GMU firmware, and high level OS must not attempt + * to disable it. The only exception is during GMU recovery, where the + * GMU driver can set GenPD’s synced_poweroff flag to allow explicitly + * disable GX GDSC in hardware. + */ +int gdsc_gx_disable(struct generic_pm_domain *domain) +{ + struct gdsc *sc = domain_to_gdsc(domain); + + if (domain->synced_poweroff) + return gdsc_disable(domain); + + /* Remove parent-supply placed in enable */ + if (sc->rsupply) + return regulator_disable(sc->rsupply); + + return 0; +} +EXPORT_SYMBOL_GPL(gdsc_gx_disable); diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 92ff6bcce7b1c..2f9665b664e60 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -93,6 +93,7 @@ int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *, struct regmap *); void gdsc_unregister(struct gdsc_desc *desc); int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain); +int gdsc_gx_disable(struct generic_pm_domain *domain); #else static inline int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, From 8c85b32e08191f42307b82dd28ac23a7f6523cfa Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 27 Apr 2026 12:08:56 +0530 Subject: [PATCH 0409/1058] FROMLIST: clk: qcom: gxclkctl: Use custom disable callback for gx_gdsc The GX GDSC represents a special GPU power domain that must not be disabled during normal runtime PM flows. As per the GMU architecture, GX GDSC should only be force-disabled during GMU/GPU recovery, where the OS explicitly resets the GX power domain. However, when managed by the generic GDSC runtime PM path, GX GDSC may be disabled during GMU runtime suspend, resulting in warnings such as: gx_clkctl_gx_gdsc status stuck at 'on' and failures in gdsc_toggle_logic() during rpm suspend. Use the newly added custom disable callback for gx_gdsc to ensure the GDSC is toggled only in recovery scenarios, while preventing unintended disable attempts during normal GMU runtime PM operations. Reported-by: Pengyu Luo Closes: https://lore.kernel.org/all/CAH2e8h4Vp9fJYAUUbOmoHSKB25wakPBvmpwa62BTRqgRQbMWuw@mail.gmail.com/ Reported-by: Alexander Koskovich Closes: https://lore.kernel.org/all/gwVAH2mJerU4dBInw8pKmOs5aQK55Q7W6q_UQAlLFCsEgX6eyvSgXAWbNNMqAX4WmPlYCKUSMhfkr5Jry4Ps5EqnxYZqEEDd3Whwv7ZXGlc=@pm.me/ Fixes: 5af11acae660 ("clk: qcom: Add a driver for SM8750 GPU clocks") Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260427-gfx-clk-fixes-v2-2-797e54b3d464@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/gxclkctl-kaanapali.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gxclkctl-kaanapali.c b/drivers/clk/qcom/gxclkctl-kaanapali.c index 7b0af0ba1e685..a39813e4e2a89 100644 --- a/drivers/clk/qcom/gxclkctl-kaanapali.c +++ b/drivers/clk/qcom/gxclkctl-kaanapali.c @@ -26,6 +26,7 @@ static struct gdsc gx_clkctl_gx_gdsc = { .pd = { .name = "gx_clkctl_gx_gdsc", .power_on = gdsc_gx_do_nothing_enable, + .power_off = gdsc_gx_disable, }, .pwrsts = PWRSTS_OFF_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, From 6125767df54ba4be2b86fd8002cdc31ea20bd941 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 27 Apr 2026 12:08:57 +0530 Subject: [PATCH 0410/1058] FROMLIST: clk: qcom: common: ensure runtime PM suspend completes on probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the clock controller is probed with 'use_rpm' enabled, the runtime PM reference is currently released using pm_runtime_put(), which may return before the runtime suspend has completed. When the clock controller device is registered through this function, calling pm_runtime_disable() immediately after pm_runtime_put() prevents the runtime suspend from completing, leaving the clock controller active and the HW rails in the ON state. Use pm_runtime_put_sync() instead to ensure the runtime PM “putV completes synchronously during probe. This does not have any functional impact, but it guarantees that the device is fully runtime-suspended before returning. Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260427-gfx-clk-fixes-v2-3-797e54b3d464@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index eec369d2173b5..2c09abaf1d2a1 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -428,7 +428,7 @@ int qcom_cc_really_probe(struct device *dev, put_rpm: if (desc->use_rpm) - pm_runtime_put(dev); + pm_runtime_put_sync(dev); return ret; } From 3b9a1fdaa08a6a860f78638c14c735a1044228be Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 27 Apr 2026 12:08:58 +0530 Subject: [PATCH 0411/1058] FROMLIST: clk: qcom: gxclkctl: Remove GX/GMxC rail votes to align with IFPC The GX GDSC control is handled through a dedicated clock controller, and the enable/disable sequencing depends on correct rail voting. The driver votes for the GX/GMxC rails and CX GDSC before toggling the GX GDSC. Currently, during GMU runtime PM resume, rails remain enabled due to upstream votes propagated via RPM-enabled devlinks and explicit pm_runtime votes on GX GDSC. This is not an expected behaviour of IFPC(Inter Frame Power Collapse) requirements of GPU as GMU firmware is expected to control these rails, except during the GPU/GMU recovery via the OS and that is where the GX GDSC should be voting for the rails (GX/GMxC and CX GDSC) before toggling the GX GDSC. Thus, disable runtime PM after successfully registering the clock controller. Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260427-gfx-clk-fixes-v2-4-797e54b3d464@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/gxclkctl-kaanapali.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gxclkctl-kaanapali.c b/drivers/clk/qcom/gxclkctl-kaanapali.c index a39813e4e2a89..1991cb6516529 100644 --- a/drivers/clk/qcom/gxclkctl-kaanapali.c +++ b/drivers/clk/qcom/gxclkctl-kaanapali.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,15 @@ MODULE_DEVICE_TABLE(of, gx_clkctl_kaanapali_match_table); static int gx_clkctl_kaanapali_probe(struct platform_device *pdev) { - return qcom_cc_probe(pdev, &gx_clkctl_kaanapali_desc); + int ret; + + ret = qcom_cc_probe(pdev, &gx_clkctl_kaanapali_desc); + if (ret) + return ret; + + pm_runtime_disable(&pdev->dev); + + return ret; } static struct platform_driver gx_clkctl_kaanapali_driver = { From e7bf03437d2c815fd83b9e9bc5ebeef1891894f8 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 25 May 2026 23:08:47 +0530 Subject: [PATCH 0412/1058] FROMLIST: clk: qcom: gcc-glymur: Move EVA clocks to critical clock list The gcc_eva_ahb_clk and gcc_eva_xo_clk branch clocks should not be registered as standalone GCC branch clocks. Drop these clocks from the GCC clock list and instead add their CBCR registers to the GCC critical clocks list to ensure they remain enabled during early boot. Fixes: efe504300a17 ("clk: qcom: gcc: Add support for Global Clock Controller") Link: https://lore.kernel.org/lkml/20260526-evacc_glymur-v1-1-b61c7755c403@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/gcc-glymur.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/clk/qcom/gcc-glymur.c b/drivers/clk/qcom/gcc-glymur.c index 2736465efdea9..32d23bdc819b7 100644 --- a/drivers/clk/qcom/gcc-glymur.c +++ b/drivers/clk/qcom/gcc-glymur.c @@ -3669,21 +3669,6 @@ static struct clk_branch gcc_disp_hf_axi_clk = { }, }; -static struct clk_branch gcc_eva_ahb_clk = { - .halt_reg = 0x9b004, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x9b004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x9b004, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gcc_eva_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_eva_axi0_clk = { .halt_reg = 0x9b008, .halt_check = BRANCH_HALT_SKIP, @@ -3714,19 +3699,6 @@ static struct clk_branch gcc_eva_axi0c_clk = { }, }; -static struct clk_branch gcc_eva_xo_clk = { - .halt_reg = 0x9b024, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x9b024, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gcc_eva_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x64000, .halt_check = BRANCH_HALT, @@ -7993,10 +7965,8 @@ static struct clk_regmap *gcc_glymur_clocks[] = { [GCC_CFG_NOC_USB_ANOC_AHB_CLK] = &gcc_cfg_noc_usb_anoc_ahb_clk.clkr, [GCC_CFG_NOC_USB_ANOC_SOUTH_AHB_CLK] = &gcc_cfg_noc_usb_anoc_south_ahb_clk.clkr, [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, - [GCC_EVA_AHB_CLK] = &gcc_eva_ahb_clk.clkr, [GCC_EVA_AXI0_CLK] = &gcc_eva_axi0_clk.clkr, [GCC_EVA_AXI0C_CLK] = &gcc_eva_axi0c_clk.clkr, - [GCC_EVA_XO_CLK] = &gcc_eva_xo_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, @@ -8545,6 +8515,8 @@ static const u32 gcc_glymur_critical_cbcrs[] = { 0x71004, /* GCC_GPU_CFG_AHB_CLK */ 0x32004, /* GCC_VIDEO_AHB_CLK */ 0x32058, /* GCC_VIDEO_XO_CLK */ + 0x9b004, /* GCC_EVA_AHB_CLK */ + 0x9b024, /* GCC_EVA_XO_CLK */ }; static const struct regmap_config gcc_glymur_regmap_config = { From b286c52b830e410a975b409fa47edfdf952b05fa Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 25 May 2026 23:08:14 +0530 Subject: [PATCH 0413/1058] FROMLIST: dt-bindings: clock: qcom: Add EVA clock and reset controller for Glymur SoC Add the device tree bindings for the enhanced video analytics(EVA) clock controller which is required on Qualcomm Glymur SoC. The controller provides clocks, resets and power domains for the EVA subsystem. Link: https://lore.kernel.org/lkml/20260526-evacc_glymur-v1-2-b61c7755c403@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,glymur-evacc.yaml | 76 +++++++++++++++++++ include/dt-bindings/clock/qcom,glymur-evacc.h | 38 ++++++++++ 2 files changed, 114 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml create mode 100644 include/dt-bindings/clock/qcom,glymur-evacc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml b/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml new file mode 100644 index 0000000000000..8315e3ce82ecf --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,glymur-evacc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm EVA Clock & Reset Controller on Glymur SoC + +maintainers: + - Taniya Das + +description: | + Qualcomm EVA clock control module which supports the clocks, resets and + power domains for the EVA instances on Glymur SoC. + + See also: + - include/dt-bindings/clock/qcom,glymur-evacc.h + +properties: + compatible: + const: qcom,glymur-evacc + + clocks: + items: + - description: Interface clock from GCC + - description: Board XO source + - description: Board XO_A source + - description: Sleep clock source + + power-domains: + description: + Power domains required for the clock controller to operate + items: + - description: MMCX power domain + - description: MXC power domain + + required-opps: + description: + Required OPP nodes for the MMCX and MXC power domains. + items: + - description: MMCX performance point + - description: MXC performance point + +required: + - compatible + - clocks + - power-domains + - required-opps + - '#power-domain-cells' + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + clock-controller@ab00000 { + compatible = "qcom,glymur-evacc"; + reg = <0x0ab00000 0x10000>; + clocks = <&gcc GCC_EVA_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; + power-domains = <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,glymur-evacc.h b/include/dt-bindings/clock/qcom,glymur-evacc.h new file mode 100644 index 0000000000000..35a7b45503516 --- /dev/null +++ b/include/dt-bindings/clock/qcom,glymur-evacc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H +#define _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H + +/* EVA_CC clocks */ +#define EVA_CC_AHB_CLK 0 +#define EVA_CC_AHB_CLK_SRC 1 +#define EVA_CC_MVS0_CLK 2 +#define EVA_CC_MVS0_CLK_SRC 3 +#define EVA_CC_MVS0_DIV_CLK_SRC 4 +#define EVA_CC_MVS0_FREERUN_CLK 5 +#define EVA_CC_MVS0_SHIFT_CLK 6 +#define EVA_CC_MVS0C_CLK 7 +#define EVA_CC_MVS0C_DIV2_DIV_CLK_SRC 8 +#define EVA_CC_MVS0C_FREERUN_CLK 9 +#define EVA_CC_MVS0C_SHIFT_CLK 10 +#define EVA_CC_PLL0 11 +#define EVA_CC_SLEEP_CLK 12 +#define EVA_CC_SLEEP_CLK_SRC 13 +#define EVA_CC_XO_CLK 14 +#define EVA_CC_XO_CLK_SRC 15 + +/* EVA_CC power domains */ +#define EVA_CC_MVS0_GDSC 0 +#define EVA_CC_MVS0C_GDSC 1 + +/* EVA_CC resets */ +#define EVA_CC_INTERFACE_BCR 0 +#define EVA_CC_MVS0_BCR 1 +#define EVA_CC_MVS0C_CLK_ARES 2 +#define EVA_CC_MVS0C_BCR 3 +#define EVA_CC_MVS0C_FREERUN_CLK_ARES 4 + +#endif /* _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H */ From dbc0fefdf9686ddcb42ae9fc47df6349ed936a81 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 26 May 2026 00:12:10 +0530 Subject: [PATCH 0414/1058] FROMLIST: clk: qcom: Add EVA clock controller driver for Glymur SoC Add the Enhanced Video Analytics (EVA) clock controller driver for the Glymur SoC. The EVACC manages the PLL, RCGs, branch clocks, GDSCs and resets for the EVA subsystem which handles vision processing workloads. Link: https://lore.kernel.org/lkml/20260526-evacc_glymur-v1-3-b61c7755c403@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 11 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/evacc-glymur.c | 453 ++++++++++++++++++++++++++++++++ 3 files changed, 465 insertions(+) create mode 100644 drivers/clk/qcom/evacc-glymur.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index fae9476910067..a6ee5ca6d7980 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -65,6 +65,17 @@ config CLK_GLYMUR_DISPCC Say Y if you want to support display devices and functionality such as splash screen. +config CLK_GLYMUR_EVACC + tristate "Glymur EVA Clock Controller" + depends on ARM64 || COMPILE_TEST + default m if ARCH_QCOM + select CLK_GLYMUR_GCC + help + Support for the Enhanced Video Analytics (EVA) clock controller on + Qualcomm Technologies, Inc. Glymur devices. + Say Y if you want to support EVA devices and functionality such as + vision processing. + config CLK_GLYMUR_GCC tristate "Glymur Global Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 042ebd64448fe..75a1fb1f3bbbf 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o obj-$(CONFIG_CLK_GLYMUR_CAMCC) += camcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o +obj-$(CONFIG_CLK_GLYMUR_EVACC) += evacc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GCC) += gcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GPUCC) += gpucc-glymur.o gxclkctl-kaanapali.o obj-$(CONFIG_CLK_GLYMUR_TCSRCC) += tcsrcc-glymur.o diff --git a/drivers/clk/qcom/evacc-glymur.c b/drivers/clk/qcom/evacc-glymur.c new file mode 100644 index 0000000000000..eab43ba922f37 --- /dev/null +++ b/drivers/clk/qcom/evacc-glymur.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_AHB_CLK, + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_EVA_CC_PLL0_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco taycan_eko_t_vco[] = { + { 249600000, 2500000000, 0 }, +}; + +/* 840.0 MHz Configuration */ +static const struct alpha_pll_config eva_cc_pll0_config = { + .l = 0x2b, + .alpha = 0xc000, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000008, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll eva_cc_pll0 = { + .offset = 0x0, + .config = &eva_cc_pll0_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct parent_map eva_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map eva_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_EVA_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &eva_cc_pll0.clkr.hw }, +}; + +static const struct parent_map eva_cc_parent_map_2[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_2[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_eva_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_ahb_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_0, + .freq_tbl = ftbl_eva_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_ahb_clk_src", + .parent_data = eva_cc_parent_data_0, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_eva_cc_mvs0_clk_src[] = { + F(840000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1050000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1350000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1500000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1650000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_1, + .freq_tbl = ftbl_eva_cc_mvs0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_clk_src", + .parent_data = eva_cc_parent_data_1, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_eva_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_sleep_clk_src = { + .cmd_rcgr = 0x80e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_2, + .freq_tbl = ftbl_eva_cc_sleep_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_sleep_clk_src", + .parent_data = eva_cc_parent_data_2, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 eva_cc_xo_clk_src = { + .cmd_rcgr = 0x80bc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_0, + .freq_tbl = ftbl_eva_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_xo_clk_src", + .parent_data = eva_cc_parent_data_0, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_regmap_div eva_cc_mvs0_div_clk_src = { + .reg = 0x809c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div eva_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch eva_cc_mvs0_clk = { + .halt_reg = 0x807c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x807c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x807c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0_freerun_clk = { + .halt_reg = 0x808c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x808c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0_shift_clk = { + .halt_reg = 0x80d8, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80d8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_clk = { + .halt_reg = 0x804c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_freerun_clk = { + .halt_reg = 0x805c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x805c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_shift_clk = { + .halt_reg = 0x80dc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80dc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc eva_cc_mvs0c_gdsc = { + .gdscr = 0x8034, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "eva_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc eva_cc_mvs0_gdsc = { + .gdscr = 0x8068, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "eva_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, + .parent = &eva_cc_mvs0c_gdsc.pd, +}; + +static struct clk_regmap *eva_cc_glymur_clocks[] = { + [EVA_CC_AHB_CLK_SRC] = &eva_cc_ahb_clk_src.clkr, + [EVA_CC_MVS0_CLK] = &eva_cc_mvs0_clk.clkr, + [EVA_CC_MVS0_CLK_SRC] = &eva_cc_mvs0_clk_src.clkr, + [EVA_CC_MVS0_DIV_CLK_SRC] = &eva_cc_mvs0_div_clk_src.clkr, + [EVA_CC_MVS0_FREERUN_CLK] = &eva_cc_mvs0_freerun_clk.clkr, + [EVA_CC_MVS0_SHIFT_CLK] = &eva_cc_mvs0_shift_clk.clkr, + [EVA_CC_MVS0C_CLK] = &eva_cc_mvs0c_clk.clkr, + [EVA_CC_MVS0C_DIV2_DIV_CLK_SRC] = &eva_cc_mvs0c_div2_div_clk_src.clkr, + [EVA_CC_MVS0C_FREERUN_CLK] = &eva_cc_mvs0c_freerun_clk.clkr, + [EVA_CC_MVS0C_SHIFT_CLK] = &eva_cc_mvs0c_shift_clk.clkr, + [EVA_CC_PLL0] = &eva_cc_pll0.clkr, + [EVA_CC_SLEEP_CLK_SRC] = &eva_cc_sleep_clk_src.clkr, + [EVA_CC_XO_CLK_SRC] = &eva_cc_xo_clk_src.clkr, +}; + +static struct gdsc *eva_cc_glymur_gdscs[] = { + [EVA_CC_MVS0_GDSC] = &eva_cc_mvs0_gdsc, + [EVA_CC_MVS0C_GDSC] = &eva_cc_mvs0c_gdsc, +}; + +static const struct qcom_reset_map eva_cc_glymur_resets[] = { + [EVA_CC_INTERFACE_BCR] = { 0x80a0 }, + [EVA_CC_MVS0_BCR] = { 0x8064 }, + [EVA_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, + [EVA_CC_MVS0C_BCR] = { 0x8030 }, + [EVA_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 }, +}; + +static struct clk_alpha_pll *eva_cc_glymur_plls[] = { + &eva_cc_pll0, +}; + +static const u32 eva_cc_glymur_critical_cbcrs[] = { + 0x80a4, /* EVA_CC_AHB_CLK */ + 0x80f8, /* EVA_CC_SLEEP_CLK */ + 0x80d4, /* EVA_CC_XO_CLK */ +}; + +static const struct regmap_config eva_cc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f50, + .fast_io = true, +}; + +static void clk_glymur_regs_configure(struct device *dev, struct regmap *regmap) +{ + /* Update CTRL_IN register */ + regmap_update_bits(regmap, 0x9f24, BIT(0), BIT(0)); +} + +static const struct qcom_cc_driver_data eva_cc_glymur_driver_data = { + .alpha_plls = eva_cc_glymur_plls, + .num_alpha_plls = ARRAY_SIZE(eva_cc_glymur_plls), + .clk_cbcrs = eva_cc_glymur_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(eva_cc_glymur_critical_cbcrs), + .clk_regs_configure = clk_glymur_regs_configure, +}; + +static const struct qcom_cc_desc eva_cc_glymur_desc = { + .config = &eva_cc_glymur_regmap_config, + .clks = eva_cc_glymur_clocks, + .num_clks = ARRAY_SIZE(eva_cc_glymur_clocks), + .resets = eva_cc_glymur_resets, + .num_resets = ARRAY_SIZE(eva_cc_glymur_resets), + .gdscs = eva_cc_glymur_gdscs, + .num_gdscs = ARRAY_SIZE(eva_cc_glymur_gdscs), + .use_rpm = true, + .driver_data = &eva_cc_glymur_driver_data, +}; + +static const struct of_device_id eva_cc_glymur_match_table[] = { + { .compatible = "qcom,glymur-evacc" }, + { } +}; +MODULE_DEVICE_TABLE(of, eva_cc_glymur_match_table); + +static int eva_cc_glymur_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &eva_cc_glymur_desc); +} + +static struct platform_driver eva_cc_glymur_driver = { + .probe = eva_cc_glymur_probe, + .driver = { + .name = "evacc-glymur", + .of_match_table = eva_cc_glymur_match_table, + }, +}; + +module_platform_driver(eva_cc_glymur_driver); + +MODULE_DESCRIPTION("QTI EVACC Glymur Driver"); +MODULE_LICENSE("GPL"); From 541dafc300c87c29597ac0c89f48bfb00837f8f5 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:49 +0530 Subject: [PATCH 0415/1058] FROMLIST: dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN clock divider. The hardware generates a fractional output frequency from a fixed input clock (typically TCXO4) using the relation Fout = Fin * (M / N), with duty cycle controlled by a separate D register. The clock output is routed over a gpio controlled pin. Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-1-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,clk-gp-mnd.yaml | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml new file mode 100644 index 0000000000000..c1688bb3d68d8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,clk-gp-mnd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Peripheral Web's PDM GP_MN Clock Divider + +maintainers: + - Taniya Das + +description: | + The Peripheral Web's PDM GP_MN clock divider receives an input clock + (TCXO4) with frequency Fin and generates an output clock with + frequency Fout = Fin * (M / N) and a duty cycle controlled by D + and routed over a gpio pin. + + The divider is configured using three registers: + + - GP_MN_CLK_MDIV: holds the M value. + - GP_MN_CLK_NDIV: holds the ones complement of (N - M). + - GP_MN_CLK_DUTY: holds the D value. + + For every N input clock cycles the GP_MN produces M output clock + cycles. D is the number of native clock cycles in which the GP_MN + output is low, counted over 2^13 native clock cycles. + + Hardware constraints: + + M <= 511 + N <= 8191 + N > 2 * M + M < D < (N - M) + M and N must be coprime (no common divisor) + +properties: + compatible: + const: qcom,clk-gp-mnd + + reg: + maxItems: 1 + + clocks: + items: + - description: PDM XO4 source clock + - description: PDM AHB bus clock for register access + + clock-names: + items: + - const: pdm_clk + - const: ahb_clk + + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + + pinctrl-0: + description: Pin configuration for the GP_MN output in the active state. + + pinctrl-names: + items: + - const: active + + assigned-clocks: + maxItems: 1 + description: Parent clock phandle used to set the input frequency. + + assigned-clock-rates: + maxItems: 1 + description: | + Rate for the parent clock in Hz. + Supported rates: 19200000, 9600000, 6400000, 4800000. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - clock-output-names + - pinctrl-0 + - pinctrl-names + - assigned-clocks + - assigned-clock-rates + +additionalProperties: false + +examples: + - | + #include + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x88d3000 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + pinctrl-0 = <&gp_mn_pin_active>; + pinctrl-names = "active"; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + #clock-cells = <0>; + }; From a90a68708257ff8cce7619ab3c07c097c4d9eebe Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:50 +0530 Subject: [PATCH 0416/1058] FROMLIST: clk: qcom: Add a driver for PDM GP_MN fractional clock divider The PDM (Pulse Density Modulation) hardware block on Qualcomm SoCs contains a GP_MN clock divider that produces a fractional output frequency from a fixed input clock (typically TCXO4): Fout = Fin * (M / N) The hardware encodes the period in the NDIV register as the 1's complement of (N - M), and controls the duty cycle via a separate DUTY register that counts the number of low-phase native clock cycles over the period N. Add a standalone platform driver for this block that uses rational_best_approximation() to find the closest M/N pair within the 9-bit M and 13-bit N hardware limits, programs the MDIV, NDIV, and DUTY registers via regmap, and implements the full clk_ops surface including determine_rate, set_rate, recalc_rate, get_duty_cycle, and set_duty_cycle. The PDM AHB bus clock is gated around every register access. Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-2-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 15 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-gp-mnd.c | 333 ++++++++++++++++++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 drivers/clk/qcom/clk-gp-mnd.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index a6ee5ca6d7980..3a275bbd5c578 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1802,4 +1802,19 @@ config SM_VIDEOCC_8450 SM8450 or SM8475 devices. Say Y if you want to support video devices and functionality such as video encode/decode. + +config QCOM_CLK_GP_MND + tristate "Qualcomm PDM GP_MN clock divider" + depends on ARM64 || COMPILE_TEST + help + Support for the Qualcomm PDM GP_MN clock divider found in PDM + (Pulse Density Modulation) hardware blocks. + Given an input clock of frequency Fin (TCXO4), the output + frequency is Fout = Fin * (M / N). For every N input cycles + the divider produces M output cycles. D controls the duty + cycle: it is the number of native clock cycles in which the + GP_MN output is low, counted over 8192 native clock cycles. + + Say Y or M if you want to support GP_MN-based frequency and + duty-cycle configuration on Qualcomm SoCs. endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 75a1fb1f3bbbf..63623651a9e1f 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -211,6 +211,7 @@ obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o +obj-$(CONFIG_QCOM_CLK_GP_MND) += clk-gp-mnd.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o obj-$(CONFIG_KRAITCC) += krait-cc.o diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c new file mode 100644 index 0000000000000..826b6b62ddc7b --- /dev/null +++ b/drivers/clk/qcom/clk-gp-mnd.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * PDM GP_MND clock divider register offsets. + * + * The hardware computes: + * Fout = Fin * (M / N) + * + * with duty cycle controlled by D, where M < D < (N - M). + * + * Register encoding: + * MDIV = M + * NDIV = ~(N - M) [1's complement of (N - M), masked to N_REG_WIDTH bits] + * DUTY = D + */ +#define GP_MND_MDIV_REG 0x0 +#define GP_MND_NDIV_REG 0x4 +#define GP_MND_DUTY_REG 0x8 + +#define GP_MND_M_WIDTH 9 +#define GP_MND_N_WIDTH 13 + +#define GP_MND_MAX_M GENMASK(GP_MND_M_WIDTH - 1, 0) +#define GP_MND_MAX_N GENMASK(GP_MND_N_WIDTH - 1, 0) + +/** + * struct clk_gp_mnd - GP_MND fractional clock divider + * @pdm_ahb_clk: AHB bus clock required for register access + * @regmap: register map for the PDM block + * @hw: handle between common and hardware-specific interfaces + * @m_val: M value (numerator) + * @n_val: N value (period) + */ +struct clk_gp_mnd { + struct clk *pdm_ahb_clk; + struct regmap *regmap; + struct clk_hw hw; + unsigned int m_val; + unsigned int n_val; +}; + +#define to_clk_gp_mnd(_hw) container_of(_hw, struct clk_gp_mnd, hw) + +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long m = 0, n = 0; + + rational_best_approximation(req->rate, req->best_parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ + if (n == 2 * m + 1) + return -EINVAL; + + req->rate = DIV_ROUND_CLOSEST_ULL((u64)req->best_parent_rate * m, n); + + return 0; +} + +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned long m = 0, n = 0; + unsigned int d_val, n_val; + int ret; + + rational_best_approximation(rate, parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty + * cycle can satisfy M < D < (N - M). Reject before touching hw. + */ + if (n == 2 * m + 1) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_MDIV_REG, m); + if (ret) + goto err_unprepare; + + /* N divider holds the 1's complement of (N - M), N_WIDTH bits wide */ + n_val = ~(n - m) & GP_MND_MAX_N; + ret = regmap_write(gp->regmap, GP_MND_NDIV_REG, n_val); + if (ret) + goto err_unprepare; + + /* Program the closest-to-50% duty cycle. */ + d_val = n / 2; + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + if (ret) + goto err_unprepare; + + gp->m_val = m; + gp->n_val = n; + +err_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static unsigned long gp_mnd_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int m_val, n_val; + int ret; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return 0; + + ret = regmap_read(gp->regmap, GP_MND_MDIV_REG, &m_val); + if (ret) + goto out_unprepare; + + m_val &= GP_MND_MAX_M; + + ret = regmap_read(gp->regmap, GP_MND_NDIV_REG, &n_val); + if (ret) + goto out_unprepare; + + /* Reverse the 1's complement encoding: N = ~NDIV_REG + M */ + n_val = (~n_val & GP_MND_MAX_N) + m_val; + +out_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return 0; + + if (!n_val) + return 0; + + gp->m_val = m_val; + gp->n_val = n_val; + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * m_val, n_val); +} + +static int gp_mnd_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val) { + duty->num = 1; + duty->den = 2; + return 0; + } + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_read(gp->regmap, GP_MND_DUTY_REG, &d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return ret; + + duty->num = d_val; + duty->den = gp->n_val; + + return 0; +} + +static int gp_mnd_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val || !gp->m_val) + return -EINVAL; + + /* D = (1 - duty) * N, giving the low-phase count */ + d_val = DIV_ROUND_UP((u64)(duty->den - duty->num) * gp->n_val, duty->den); + + /* Hardware constraint: M < D < (N - M) */ + if (d_val <= gp->m_val || d_val >= (gp->n_val - gp->m_val)) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static const struct clk_ops clk_gp_mnd_ops = { + .determine_rate = gp_mnd_clk_determine_rate, + .set_rate = gp_mnd_clk_set_rate, + .recalc_rate = gp_mnd_clk_recalc_rate, + .get_duty_cycle = gp_mnd_clk_get_duty_cycle, + .set_duty_cycle = gp_mnd_clk_set_duty_cycle, +}; + +static const struct regmap_config gp_mnd_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int clk_gp_mnd_probe(struct platform_device *pdev) +{ + struct clk_parent_data parent_data = { .index = 0 }; + struct clk_init_data init = { + .ops = &clk_gp_mnd_ops, + .parent_data = &parent_data, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }; + struct device *dev = &pdev->dev; + struct clk_gp_mnd *gp; + struct clk *clk; + struct pinctrl *pin; + struct pinctrl_state *pin_default_state; + void __iomem *base; + int ret; + + gp = devm_kzalloc(dev, sizeof(*gp), GFP_KERNEL); + if (!gp) + return -ENOMEM; + + gp->pdm_ahb_clk = devm_clk_get(dev, "ahb_clk"); + if (IS_ERR(gp->pdm_ahb_clk)) + return dev_err_probe(dev, PTR_ERR(gp->pdm_ahb_clk), + "failed to get ahb_clk\n"); + + clk = devm_clk_get(dev, "pdm_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* Set default rate if not already configured */ + if (!clk_get_rate(clk)) { + ret = clk_set_rate(clk, 19200000); + if (ret) + dev_warn(dev, "failed to set default pdm_clk rate\n"); + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "failed to map PDM registers\n"); + + gp->regmap = devm_regmap_init_mmio(dev, base, &gp_mnd_regmap_config); + if (IS_ERR(gp->regmap)) + return dev_err_probe(dev, PTR_ERR(gp->regmap), + "failed to init regmap\n"); + + ret = of_property_read_string_index(dev->of_node, + "clock-output-names", 0, + &init.name); + if (ret) + return dev_err_probe(dev, ret, "missing clock-output-names\n"); + + gp->hw.init = &init; + + pin = devm_pinctrl_get(dev); + if (IS_ERR(pin)) + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); + + pin_default_state = pinctrl_lookup_state(pin, "active"); + if (IS_ERR(pin_default_state)) + return dev_err_probe(dev, PTR_ERR(pin_default_state), + "missing pinctrl default state\n"); + + ret = pinctrl_select_state(pin, pin_default_state); + if (ret) + return dev_err_probe(dev, ret, + "failed to select pinctrl default state\n"); + + ret = devm_clk_hw_register(dev, &gp->hw); + if (ret) + return dev_err_probe(dev, ret, + "failed to register gp_mnd clock\n"); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); +} + +static const struct of_device_id clk_gp_mnd_match_table[] = { + { .compatible = "qcom,clk-gp-mnd" }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); + +static struct platform_driver clk_gp_mnd_driver = { + .probe = clk_gp_mnd_probe, + .driver = { + .name = "qcom-clk-gp-mnd", + .of_match_table = clk_gp_mnd_match_table, + }, +}; +module_platform_driver(clk_gp_mnd_driver); + +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); +MODULE_LICENSE("GPL"); From 80c49732e8d0915b1dd6745e1ceebf50e0c6b1b0 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 4 Jun 2026 10:33:28 +0530 Subject: [PATCH 0417/1058] PENDING: dt-bindings: ptp: Add support for Qualcomm TSCSS module Qualcomm TSCSS is a time synchronization subsystem composed of two main blocks: the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). The TSC block is a timestamp generator that maintains a running counter used for system timekeeping. The ETU block captures timestamps for external events using one of the available timestamp sources. Signed-off-by: Imran Shaik --- .../devicetree/bindings/ptp/qcom,tsc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Documentation/devicetree/bindings/ptp/qcom,tsc.yaml diff --git a/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml new file mode 100644 index 0000000000000..092e267e29da4 --- /dev/null +++ b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ptp/qcom,tsc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Timestamp Counter Subsystem (TSCSS) + +maintainers: + - Imran Shaik + - Taniya Das + +description: + Qualcomm TSCSS is a time synchronization subsystem composed of two main + blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). + + The TSC block is a timestamp generator that maintains a running counter used + for system timekeeping. The ETU block captures timestamps for external events + using one of the available timestamp sources. + +properties: + compatible: + enum: + - qcom,tsc + + reg: + maxItems: 2 + + reg-names: + items: + - const: tsc + - const: etu + + clocks: + items: + - description: TSC AHB clock + - description: TSC cntr clock + - description: TSC ETU clock + + clock-names: + items: + - const: cfg_ahb + - const: cntr + - const: etu + + interrupts: + maxItems: 1 + + interrupt-names: + items: + - const: etu_summary_irq + + qcom,tsc-nsec-update: + description: + Indicates the TSC counters have values in nanoseconds, rather than + in secs and nanoseconds. + type: boolean + + qcom,etu-slice: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU slice numbers corresponding to the ETU sel. + In case this property is not defined the sel number will be + considered as the slice number for ETU offset calculation. + + qcom,etu-event-sel: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU event sel numbers for the corresponding ETU slice + numbers. + + qcom,etu-event-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + ETU event sel names for the corresponding event sel numbers. + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + tsc: tsc@1c80000 { + compatible = "qcom,tsc"; + reg = <0x01c80000 0x2000>, + <0x01ca0000 0x20000>; + reg-names = "tsc", "etu"; + clocks = <&tscss_ahb_clock>, <&tscss_cntr_clock>, + <&tscss_cntr_clock>; + clock-names = "cfg_ahb", "cntr", "etu"; + interrupts = ; + interrupt-names = "etu_summary_irq"; + qcom,etu-slice = <10 11>; + qcom,etu-event-sel = <10 11>; + qcom,etu-event-names = "gps_pps", "tod_pps"; + qcom,tsc-nsec-update; + }; From ceb890d6c52056b8f963de767db81befce41c35e Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 31 Mar 2026 07:04:51 +0530 Subject: [PATCH 0418/1058] PENDING: ptp: Add support for Qualcomm TSCSS hardware Add support for the Qualcomm TSCSS hardware, that is a time synchronization subsystem composed of two main blocks: the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). Signed-off-by: Imran Shaik --- drivers/ptp/Kconfig | 9 + drivers/ptp/Makefile | 1 + drivers/ptp/ptp_qcom_tsc.c | 842 +++++++++++++++++++++++++++++++++++++ 3 files changed, 852 insertions(+) create mode 100644 drivers/ptp/ptp_qcom_tsc.c diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index b93640ca08b72..0a1f3d405aa4a 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -263,4 +263,13 @@ config PTP_NETC_V4_TIMER synchronization. It also supports periodic output signal (e.g. PPS) and external trigger timestamping. +config PTP_QCOM_CLOCK_TSC + tristate "Qualcomm TSC as PTP clock" + depends on COMMON_CLK && PTP_1588_CLOCK + help + This driver adds support for using the Qualcomm Timestamp Counter (TSC) + as a PTP clock the requires for time stamping of PTP packets. + It also registers interrupts for Event Timestamp Unit (ETU) and updates + the TSC timestamps to PTP clock event. + endmenu diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index bdc47e284f14e..6789b2a517b1d 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_OCP) += ptp_ocp.o obj-$(CONFIG_PTP_DFL_TOD) += ptp_dfl_tod.o obj-$(CONFIG_PTP_S390) += ptp_s390.o obj-$(CONFIG_PTP_NETC_V4_TIMER) += ptp_netc.o +obj-$(CONFIG_PTP_QCOM_CLOCK_TSC) += ptp_qcom_tsc.o diff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c new file mode 100644 index 0000000000000..4df38665a56e6 --- /dev/null +++ b/drivers/ptp/ptp_qcom_tsc.c @@ -0,0 +1,842 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QCOM TSC PTP : Linux driver for Time Stamp Counter Hardware. + * + */ + +#define pr_fmt(fmt) "qcom_tsc: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offset definitions */ +#define TSCSS_TSC_CONTROL_CNTCR 0x0 +#define TSCSS_TSC_CONTROL_CNTCV_LO 0x8 +#define TSCSS_TSC_CONTROL_CNTCV_HI 0xC +#define TSCSS_TSC_CONTROL_CNTCV_FRAC 0x10 +#define TSCSS_TSC_SLEEP_INCR_VAL_LO 0x24 +#define TSCSS_TSC_SLEEP_INCR_VAL_HI 0x28 +#define TSCSS_TSC_DRIFT_CORRECT_INCR_VAL 0x2C +#define TSCSS_TSC_DRIFT_CORRECT_DURATION 0x30 +#define TSCSS_TSC_DRIFT_CORRECT_CMD 0x34 +#define TSCSS_TSC_ROLLOVER_VAL 0x3C +#define TSCSS_TSC_SPARE 0x40 +#define TSCSS_TSC_OFFSET_LO 0x50 +#define TSCSS_TSC_OFFSET_HI 0x54 +#define TSCSS_TSC_FUSA_CFG_STAT 0xF54 +#define TSCSS_TSC_READ_CNTCV_LO 0x1000 +#define TSCSS_TSC_READ_CNTCV_HI 0x1004 +#define TSCSS_TSC_HW_PRELOAD_VAL_LO 0x0060 +#define TSCSS_TSC_HW_PRELOAD_VAL_HI 0x0064 + +#define TSCSS_TSC_SLICE_ETU_CFG 0x0 +#define TSCSS_TSC_SLICE_ETU_STATUS 0x4 +#define TSCSS_ETU_SLICE_TSC_TS_LO 0x8 +#define TSCSS_ETU_SLICE_TSC_TS_HI 0xC +#define TSCSS_ETU_SLICE_TS_EVENT_TYPE 0x10 +#define TSCSS_ETU_SLICE_GCTR_TS_LO 0x20 +#define TSCSS_ETU_SLICE_GCTR_TS_HI 0x24 +#define TSCSS_ETU_SLICE_FIFO_CLR 0x30 +#define TSCSS_ETU_SLICE_SW_TRIG_CFG 0x34 +#define TSCSS_ETU_SLICE_TIMER_TRIG_PERIOD 0x38 +#define MAX_ETU_SLICE 16 + +#define DRIFT_CORRECT_MAX_PERIOD 0x1FFFF +#define DRIFT_CORRECT_MAX_RES 0x7FFFC0 + +#define TSC_PRELOAD_POLLING_DELAY_MS 100 +#define NSEC_SHFT 32 +#define NSEC_MASK GENMASK_ULL(31, 0) +#define NSEC 1000000000ULL +#define XO_MHZ 19200000 +#define TSCSS_TSC_ETU_SLICE_BASE(reg_base, num, offset) \ + (reg_base + num * 0x1000 + offset) + +struct qcom_etu_slice { + char name[10]; + struct ptp_clock *ptp_clock; + void __iomem *etu_baseaddr; + u64 etu_tsc_timestamp; + u64 last_sec; + u64 global_qtimer; + int extts_enable; + int extts_irq; + int extts_index; + int extts_event_sel; + int extts_slice_num; + int extts_event_type; + u32 etu_tsc_sec; + u32 etu_tsc_nsec; + u32 etu_gctr_sec; + u32 etu_gctr_nsec; + bool extts_present; +}; + +struct qcom_ptp_tsc { + struct device *dev; + void __iomem *baseaddr; + void __iomem *etu_baseaddr; + struct clk *tsc_cfg_ahb_clk; + struct clk *tsc_cntr_clk; + struct clk *tsc_etu_clk; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + struct qcom_etu_slice etu_slice[MAX_ETU_SLICE]; + int pps_enable; + int total_etu_cnt; + bool tsc_nsec_update; + bool tsc_hw_preload; + spinlock_t reg_lock; + struct delayed_work tsc_preload_poll_work; + u32 configured_slice_mask; +}; + +static void tsc_preload_poll(struct work_struct *work) +{ + struct qcom_ptp_tsc *timer = container_of(work, struct qcom_ptp_tsc, + tsc_preload_poll_work.work); + u32 regval; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + /* Check for the HW_PRELOAD_STATUS and disable HW_PRELOAD */ + if (!(regval & BIT(14))) { + regval &= ~BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + pr_info("TSC CNTCR: 0x%x HW_PRELOAD is disabled\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); + return; + } + + pr_debug("TSC CNTCR: 0x%x HW_PRELOAD_STATUS is not cleared\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); +} + +static int qcom_ptp_tsc_is_enabled(void __iomem *addr) +{ + return readl_relaxed(addr + TSCSS_TSC_CONTROL_CNTCR) & BIT(0); +} + +static void qcom_tod_read(struct qcom_ptp_tsc *timer, struct timespec64 *ts) +{ + u64 temp, final; + u32 sec, nsec; + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + pr_debug("TSC is not enabled\n"); + return; + } + + sec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_HI); + nsec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_LO); + + pr_debug("CNTR_HI: 0x%x, sec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI), sec); + pr_debug("CNTR_LO: 0x%x nsec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO), nsec); + + if (timer->tsc_nsec_update) { + temp = sec; + final = (temp << NSEC_SHFT) | nsec; + sec = div_u64_rem(final, NSEC, &nsec); + pr_debug("tsc_nsec_update: %d, sec %u, nsec %u\n", + timer->tsc_nsec_update, sec, nsec); + } + + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + +static void qcom_ptp_enable_tsc_hw_preload(struct qcom_ptp_tsc *timer, struct timespec64 ts) +{ + u32 regval; + int timeout = 500; + + /* Enable HW_PRELOAD */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Program PRELOAD registers */ + writel_relaxed(ts.tv_sec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI); + writel_relaxed(ts.tv_nsec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO); + + pr_debug("HW_PRELOAD_VAL_HI: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI)); + pr_debug("HW_PRELOAD_VAL_LO: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO)); + + /* Check for the HW_PRELOAD_STATUS and start poll thread */ + while (timeout-- > 0) { + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + if (regval & BIT(14)) { + pr_debug("TSC CNTR: 0x%x HW_PRELOAD is enabled\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); + return; + } + udelay(1); + } + + pr_warn("TSC CNTR: 0x%x HW_PRELOAD enable failed\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); +} + +static int qcom_ptp_update_tsc_cntr(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + u64 timestamp = 0; + u32 regval; + + /* Update to 1ns resolution */ + if (timer->tsc_nsec_update) { + timestamp = offset.tv_sec * NSEC + offset.tv_nsec; + writel_relaxed((timestamp >> NSEC_SHFT), + timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(timestamp & NSEC_MASK, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } else { + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } + + pr_debug("Timestamp %llu: sec: %lld, nsec: %ld\n", timestamp, + offset.tv_sec, offset.tv_nsec); + + pr_debug("CNTR_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTR_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); + + /* Enable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(0); + + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + return 0; +} + +static void qcom_ptp_update_tsc_offset(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + struct timespec64 tod; + u32 regval; + + if (timer->tsc_nsec_update) { + /* Read TOD and add delta */ + qcom_tod_read(timer, &tod); + tod = timespec64_add(tod, offset); + + pr_debug("%s disable the counter and re-init with tod+delta\n", __func__); + /* Disable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval &= ~BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Re-initialize the counter with updated time */ + qcom_ptp_update_tsc_cntr(timer, tod); + } else { + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_OFFSET_LO); + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_OFFSET_HI); + + pr_debug("OFFSET_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_HI)); + pr_debug("OFFSET_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_LO)); + } + + pr_debug("CNTCV_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTCV_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); +} + +static int qcom_ptp_normal_drift_correction(struct qcom_ptp_tsc *timer, long delta) +{ + u64 regval = 0, period, subperiod = 4, res = 64, incval = 0, multiple, total_cycles; + bool is_jump; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + if (regval & BIT(1)) { + pr_debug("Previous drift correction is still in progress...\n"); + return -EINVAL; + } + + regval = 0; + + if (delta == 0) + return 0; + + if (delta < 0) { + /* Swallow the counter */ + delta = -delta; + regval &= ~BIT(31); + is_jump = false; + + if (delta > DRIFT_CORRECT_MAX_RES) { + period = DRIFT_CORRECT_MAX_PERIOD; + pr_debug("Delta(%ldns) > 8.3ms, program max swallow resolution\n", delta); + } else { + period = div_u64(delta, res); + } + } else { + /* Jump the counter */ + regval |= BIT(31); + is_jump = true; + + total_cycles = delta / res; + multiple = total_cycles / DRIFT_CORRECT_MAX_RES; + pr_debug("total_cycles = %lld multiple = %lld\n", total_cycles, multiple); + if (multiple == 0) { + if (delta < res) { + period = 1; + incval = res + delta; + } else { + period = div_u64(delta, res); + incval = res * 2; + } + } else { + pr_debug("Delta(%ldns) > 8.3ms, do nothing...\n", delta); + return 0; + } + } + + regval |= subperiod; + regval |= (period << 12); + + pr_debug("delta:%ld period:%lld subperiod:%lld is_jump:%d regval:0x%llx\n", + delta, period, subperiod, is_jump, regval); + + /* Update jump/swallow, period, subperiod */ + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION); + + /* Update the INCR VAL */ + writel_relaxed(incval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL); + + /* Trigger the drift correction */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + regval |= BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + + readl_poll_timeout(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD, + regval, !(regval & BIT(1)), 5, 500); + + pr_debug("duration = 0x%x incr_val = 0x%x cmd = 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD)); + + return 0; +} + +/* + * PTP clock operations + */ +static int qcom_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + return qcom_ptp_normal_drift_correction(timer, scaled_ppm_to_ppb(scaled_ppm)); +} + +static int qcom_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 offset; + + spin_lock_irqsave(&timer->reg_lock, flags); + + offset = ns_to_timespec64(delta); + pr_debug("sec: %lld, nsec: %ld\n", offset.tv_sec, offset.tv_nsec); + + qcom_ptp_update_tsc_offset(timer, offset); + spin_unlock_irqrestore(&timer->reg_lock, flags); + + return 0; +} + +static int qcom_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + spin_lock_irqsave(&timer->reg_lock, flags); + qcom_tod_read(timer, ts); + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +/** + * qcom_ptp_settime - Set the current time on the hardware clock + * @ptp: ptp clock structure + * @ts: timespec64 containing the new time for the cycle counter + */ +static int qcom_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, ptp_clock_info); + struct timespec64 delta, tod; + struct timespec64 offset; + unsigned long flags; + int ret; + + spin_lock_irqsave(&timer->reg_lock, flags); + + pr_debug("TS.sec %lld TS.tv_nsec %ld\n", ts->tv_sec, ts->tv_nsec); + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + /* Update the Counter */ + offset.tv_sec = ts->tv_sec; + offset.tv_nsec = ts->tv_nsec; + + ret = qcom_ptp_update_tsc_cntr(timer, offset); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return ret; + } + + /* Get the current timer value */ + qcom_tod_read(timer, &tod); + + /* Subtract the current reported time from our desired time */ + delta = timespec64_sub((struct timespec64)*ts, tod); + + pr_debug("Delta.sec %lld delta.tv_nsec %ld\n", delta.tv_sec, delta.tv_nsec); + + /* Update the Counter */ + qcom_ptp_update_tsc_offset(timer, delta); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +static void qcom_etu_event_handler(struct qcom_etu_slice *etu, struct qcom_ptp_tsc *timer) +{ + struct ptp_clock_event extts_event; + u64 ts, temp; + u32 regval; + + etu->etu_tsc_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_HI)); + + etu->etu_tsc_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_LO)); + + if (!timer->tsc_nsec_update) { + ts = etu->etu_tsc_sec * NSEC + etu->etu_tsc_nsec; + } else { + temp = etu->etu_tsc_sec; + ts = (temp << NSEC_SHFT) | etu->etu_tsc_nsec; + } + + if (ts != etu->etu_tsc_timestamp) { + extts_event.type = PTP_CLOCK_EXTTS; + extts_event.index = etu->extts_index; + extts_event.timestamp = ts; + + pr_debug("type:%d index:%d timestamp:%llu\n", extts_event.type, + extts_event.index, extts_event.timestamp); + + ptp_clock_event(etu->ptp_clock, &extts_event); + } + etu->etu_tsc_timestamp = ts; + + pr_debug("etu_tsc_sec:%u etu_tsc_nsec:%u etu_tsc_timestamp:%llu\n", + etu->etu_tsc_sec, etu->etu_tsc_nsec, etu->etu_tsc_timestamp); + + etu->etu_gctr_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_HI)); + + etu->etu_gctr_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_LO)); + + etu->extts_event_type = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TS_EVENT_TYPE)); + + /* Concatenate GCTR_TS_HI(31:0) & GCTR_TS_LO(31:8) and divide with 19.2MHz */ + etu->global_qtimer = (((u64)etu->etu_gctr_sec << 24) | + (etu->etu_gctr_nsec >> 8)) / XO_MHZ; + + pr_debug("etu_gctr_sec:%u etu_gctr_nsec:%u global_qtimer:%llx extts_event_type %d\n", + etu->etu_gctr_sec, etu->etu_gctr_nsec, + etu->global_qtimer, etu->extts_event_type); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + regval &= ~BIT(17); + regval &= ~BIT(16); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + + /* FIFO CLR */ + writel_relaxed(0x7, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_FIFO_CLR)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); +} + +static irqreturn_t qcom_etu_summary_irq_handler(int irq, void *data) +{ + struct qcom_etu_slice *etu; + struct qcom_ptp_tsc *timer; + unsigned long mask; + u32 status; + int slice; + + timer = data; + mask = timer->configured_slice_mask; + + for_each_set_bit(slice, &mask, MAX_ETU_SLICE) { + etu = &timer->etu_slice[slice]; + status = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + slice, TSCSS_TSC_SLICE_ETU_STATUS)); + + if (etu->extts_enable && (status & GENMASK(5, 0))) + qcom_etu_event_handler(etu, timer); + } + + return IRQ_HANDLED; +} + +static void qcom_tsc_configure_etu(struct qcom_ptp_tsc *timer, int slice) +{ + void __iomem *base = timer->etu_baseaddr; + u32 regval; + + /* Register for the IRQ */ + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + regval |= (timer->etu_slice[slice].extts_event_sel << 4) & GENMASK(9, 4); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + /* Interrupt MASK enable */ + regval |= BIT(31); + + /* Enable rising edge config */ + regval |= BIT(0); + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Bitmask of configured slices.*/ + timer->configured_slice_mask |= BIT(slice); + + pr_debug("ETU_SLICE#%d: 0x%x\n", slice, + readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG))); +} + +static int qcom_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 ts; + int slice; + + pr_debug("Request Type %d\n", rq->type); + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + timer->pps_enable = 1; + return 0; + case PTP_CLK_REQ_EXTTS: + pr_debug("PTP_CLK_REQ_EXTTS: Request external Index %d\n", rq->extts.index); + + if (rq->extts.index >= timer->total_etu_cnt) + return -EINVAL; + else if (!on) + return 0; + + for (slice = 0; slice < MAX_ETU_SLICE; slice++) { + if (!timer->etu_slice[slice].extts_present) + continue; + + if (rq->extts.index == timer->etu_slice[slice].extts_index) { + pr_debug("slice %d, index %d, etu_index %d\n", slice, + rq->extts.index, timer->etu_slice[slice].extts_index); + qcom_tsc_configure_etu(timer, + timer->etu_slice[slice].extts_slice_num); + timer->etu_slice[slice].extts_enable = true; + } + + } + return 0; + case PTP_CLK_REQ_PEROUT: + if (timer->tsc_hw_preload) { + if (!rq->perout.period.sec) { + /* Get the current timer value */ + qcom_tod_read(timer, &ts); + } else { + pr_debug("PTP_CLK_REQ_PEROUT: sec:%lld nsec:%u\n", + rq->perout.period.sec, rq->perout.period.nsec); + ts.tv_sec = rq->perout.period.sec; + ts.tv_nsec = rq->perout.period.nsec; + } + + /* Preload TSC with tv_sec += 1 and tv_nsec = 0 values */ + ts.tv_sec += 1; + ts.tv_nsec = 0; + qcom_ptp_enable_tsc_hw_preload(timer, ts); + } + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info qcom_ptp_clock_info = { + .owner = THIS_MODULE, + .name = "QCOM TSC", + .max_adj = 999999999, + /* The number of external time stamp channels. */ + .n_ext_ts = 1, + .n_per_out = 1, + .pps = 1, + .adjfine = qcom_ptp_adjfine, + .adjtime = qcom_ptp_adjtime, + .gettime64 = qcom_ptp_gettime, + .settime64 = qcom_ptp_settime, + .enable = qcom_ptp_enable, +}; + +/* module operations */ + +static void qcom_ptp_tsc_remove(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer = platform_get_drvdata(pdev); + + if (timer->ptp_clock) { + ptp_clock_unregister(timer->ptp_clock); + timer->ptp_clock = NULL; + } + + if (timer->tsc_etu_clk) + clk_disable_unprepare(timer->tsc_etu_clk); + + if (timer->tsc_cntr_clk) + clk_disable_unprepare(timer->tsc_cntr_clk); + + if (timer->tsc_cfg_ahb_clk) + clk_disable_unprepare(timer->tsc_cfg_ahb_clk); + +} + +static int qcom_tsc_etu_get_data(struct platform_device *pdev, + struct qcom_ptp_tsc *timer) +{ + struct device *dev = &pdev->dev; + struct resource *r_mem; + struct pinctrl *pinctrl; + int ret, cnt, i, summary_irq; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r_mem) { + dev_err(&pdev->dev, "No ETU resource defined\n"); + return 0; + } + + timer->etu_baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->etu_baseaddr)) + return PTR_ERR(timer->etu_baseaddr); + + summary_irq = platform_get_irq_byname(pdev, "etu_summary_irq"); + + if (summary_irq > 0) { + ret = devm_request_irq(dev, summary_irq, + qcom_etu_summary_irq_handler, IRQF_TRIGGER_HIGH, + "etu_summary_irq", timer); + if (ret) { + dev_err(&pdev->dev, "Request_summary_irq failed:%d: err:%d\n", + summary_irq, ret); + return ret; + } + } + + cnt = of_property_count_elems_of_size(dev->of_node, "qcom,etu-event-sel", + sizeof(u32)); + pr_debug("Number of event-sel %d\n", cnt); + + for (i = 0; i < cnt; i++) { + const char *name; + u32 sel, slice; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-event-sel", i, &sel); + if (ret) + break; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-slice", i, &slice); + if (ret) { + pr_debug("etu-slice property does not exist, configure using sel value\n"); + slice = sel; + } + + timer->etu_slice[slice].etu_baseaddr = timer->etu_baseaddr; + timer->etu_slice[slice].extts_index = i; + timer->etu_slice[slice].extts_event_sel = sel; + timer->etu_slice[slice].extts_slice_num = slice; + of_property_read_string_index(dev->of_node, + "qcom,etu-event-names", i, &name); + + strscpy(timer->etu_slice[slice].name, name, sizeof(timer->etu_slice[slice].name)); + + timer->etu_slice[slice].extts_irq = summary_irq; + + pr_debug("sel: %d, index: %d, slice-num:%d slice-name: %s, IRQ: %d\n", sel, + timer->etu_slice[slice].extts_index, slice, + timer->etu_slice[slice].name, timer->etu_slice[slice].extts_irq); + + timer->etu_slice[slice].extts_present = true; + timer->etu_slice[slice].ptp_clock = timer->ptp_clock; + } + + timer->total_etu_cnt = cnt; + timer->ptp_clock_info.n_ext_ts = cnt; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_info(&pdev->dev, "No default pinctrl found\n"); + + return 0; +} + +static int qcom_ptp_tsc_probe(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer; + struct resource *r_mem; + u32 cntr_val; + int ret; + + timer = devm_kzalloc(&pdev->dev, sizeof(*timer), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + timer->dev = &pdev->dev; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r_mem) { + dev_err(&pdev->dev, "no IO resource defined\n"); + return -ENXIO; + } + + timer->baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->baseaddr)) + return PTR_ERR(timer->baseaddr); + + spin_lock_init(&timer->reg_lock); + + timer->tsc_cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb"); + if (IS_ERR(timer->tsc_cfg_ahb_clk)) { + if (PTR_ERR(timer->tsc_cfg_ahb_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get CFG AHB clock\n"); + return PTR_ERR(timer->tsc_cfg_ahb_clk); + } + + timer->tsc_cntr_clk = devm_clk_get(&pdev->dev, "cntr"); + if (IS_ERR(timer->tsc_cntr_clk)) { + if (PTR_ERR(timer->tsc_cntr_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get Counter clock\n"); + return PTR_ERR(timer->tsc_cntr_clk); + } + + timer->tsc_etu_clk = devm_clk_get(&pdev->dev, "etu"); + if (IS_ERR(timer->tsc_etu_clk)) { + if (PTR_ERR(timer->tsc_etu_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get ETU clock\n"); + return PTR_ERR(timer->tsc_etu_clk); + } + + ret = clk_prepare_enable(timer->tsc_cfg_ahb_clk); + if (ret) { + pr_debug("Failed to enable AHB clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_cntr_clk); + if (ret) { + pr_debug("Failed to enable counter clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_etu_clk); + if (ret) { + pr_debug("Failed to enable etu clock\n"); + return ret; + } + + timer->tsc_nsec_update = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-nsec-update"); + + timer->tsc_hw_preload = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-hw-preload"); + + if (timer->tsc_hw_preload) + INIT_DEFERRABLE_WORK(&timer->tsc_preload_poll_work, tsc_preload_poll); + + timer->ptp_clock_info = qcom_ptp_clock_info; + + timer->ptp_clock = ptp_clock_register(&timer->ptp_clock_info, &pdev->dev); + if (IS_ERR(timer->ptp_clock)) { + ret = PTR_ERR(timer->ptp_clock); + dev_err(&pdev->dev, "Failed to register ptp clock\n"); + goto out; + } + + qcom_tsc_etu_get_data(pdev, timer); + + if (!timer->tsc_nsec_update) { + cntr_val = (timer->tsc_hw_preload ? 0x1D8 : 0x1CC); + writel_relaxed(0x3B9AC9FF, timer->baseaddr + TSCSS_TSC_ROLLOVER_VAL); + } else { + cntr_val = 0x18C; + } + + writel_relaxed(cntr_val, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + pr_info("TSC CNTR 0x%x tsc-nsec-update %d tsc-hw-preload %d\n", + readl_relaxed(timer->baseaddr), timer->tsc_nsec_update, timer->tsc_hw_preload); + + platform_set_drvdata(pdev, timer); + + return 0; +out: + timer->ptp_clock = NULL; + return ret; +} + +static const struct of_device_id tsc_of_match[] = { + { .compatible = "qcom,tsc", }, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, tsc_of_match); + +static struct platform_driver qcom_ptp_tsc_driver = { + .probe = qcom_ptp_tsc_probe, + .remove = qcom_ptp_tsc_remove, + .driver = { + .name = "qcom_ptp_tsc", + .of_match_table = tsc_of_match, + }, +}; + +module_platform_driver(qcom_ptp_tsc_driver); + +MODULE_DESCRIPTION("PTP QCOM TSC driver"); +MODULE_LICENSE("GPL"); From 675862d8b0dec006a7581c4ff88d8d9e69aff7ad Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Sat, 27 Jun 2026 20:45:39 +0530 Subject: [PATCH 0419/1058] WORKAROUND: clk: qcom: gdsc: Conditionally disable GDSC if synced_poweroff flag is set USB, PCIE GDSCs require the GDSC to left ON in USB host mode and PCIE non-D3 cold usecases even during system suspend. To handle this use the GenPD's synced_poweroff flag which can be set by USB/PCIE drivers if they require the GDSC to be disabled before suspend. If the GDSC is required to be left ON, the USB/PCIE drivers can avoid setting this flag before suspend. Add support for custom gdsc disable callback that disables GDSC based on GenPD's synced_poweroff flag. Signed-off-by: Jagadeesh Kona Signed-off-by: Krishna Kurapati --- drivers/clk/qcom/gdsc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 2f9665b664e60..1acb5c97ccd96 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -94,6 +94,7 @@ int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *, void gdsc_unregister(struct gdsc_desc *desc); int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain); int gdsc_gx_disable(struct generic_pm_domain *domain); +#define gdsc_synced_poweroff_disable gdsc_gx_disable #else static inline int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, From 8c2f864be2e1d09708beb252cf8399e4c0026cc0 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Sat, 27 Jun 2026 20:47:20 +0530 Subject: [PATCH 0420/1058] WORKAROUND: clk: qcom: gcc: Use gdsc_synced_poweroff_disable for USB GDSC's Use gdsc_synced_poweroff_disable callback for USB GDSC's on qcs615 platforms so these GDSC's get disabled only when consumer drivers explicitly invoke dev_pm_genpd_synced_poweroff() API before suspend. Signed-off-by: Jagadeesh Kona Signed-off-by: Krishna Kurapati --- drivers/clk/qcom/gcc-qcs615.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-qcs615.c b/drivers/clk/qcom/gcc-qcs615.c index 5b3b8dd4f114b..4e2a9879951f2 100644 --- a/drivers/clk/qcom/gcc-qcs615.c +++ b/drivers/clk/qcom/gcc-qcs615.c @@ -2675,6 +2675,7 @@ static struct gdsc usb20_sec_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb20_sec_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; @@ -2686,6 +2687,7 @@ static struct gdsc usb30_prim_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb30_prim_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; From 00c8325995f8d0fb1884346bf79879dd0dcc22c1 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 27 Jun 2026 20:48:23 +0530 Subject: [PATCH 0421/1058] WORKAROUND: usb: dwc3: qcom: Add support to keep GDSC On during host mode bus suspend On targets pre-sm8750, when DUT enters bus suspend in host mode, there is a xHCI crash seen on resume. During bus susend use case if the device is wakeup capable, the GDSC needs to be kept ON to retain memory and avoid SMMU faults. Set synced_poweroff flag to false to ensure GDSC is turned OFF during cable disconnect or non-bus suspend host mode scenario. Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f43f73ac36ff1..4dfadfa0dd86a 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "core.h" #include "glue.h" @@ -362,6 +363,8 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) for (i = 0; i < qcom->num_ports; i++) qcom->ports[i].usb2_speed = dwc3_qcom_read_usb2_speed(qcom, i); dwc3_qcom_enable_interrupts(qcom); + } else { + dev_pm_genpd_synced_poweroff(qcom->dev); } qcom->is_suspended = true; From da8d02ca2933cc17c36df137b962e31cb9f2a52e Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:03 +0530 Subject: [PATCH 0422/1058] FROMLIST: iommu/arm-smmu: Add interconnect bandwidth voting support On some SoCs the SMMU registers require an active interconnect bandwidth vote to be accessible. While other clients typically satisfy this requirement implicitly, certain corner cases (e.g. during sleep/wakeup transitions) can leave the SMMU without a vote, causing intermittent register access failures. Add support for an optional interconnect path to the arm-smmu driver and vote for bandwidth while the SMMU is active. The path is acquired from DT if present and ignored otherwise. The bandwidth vote is enabled before accessing SMMU registers during probe and runtime resume, and released during runtime suspend and on error paths. Generally, from an architectural perspective, GEM_NOC and DDR are expected to have an active vote whenever the adreno_smmu block is powered on. In most common use cases, this requirement is implicitly satisfied because other GPU-related clients (for example, the GMU device) already hold a GEM_NOC vote when adreno_smmu is enabled. However, there are certain corner cases, such as during sleep/wakeup transitions, where the GEM_NOC vote can be removed before adreno_smmu is powered down. If adreno_smmu is then accessed while the interconnect vote is missing, it can lead to the observed failures. Because of the precise ordering involved, this scenario is difficult to reproduce consistently. (also GDSC is involved in adreno usecases can have an independent vote) Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-2-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 57 ++++++++++++++++++++++++++- drivers/iommu/arm/arm-smmu/arm-smmu.h | 2 + 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 83a6fac172ae9..744ff8b4d5733 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -53,6 +53,11 @@ #define MSI_IOVA_BASE 0x8000000 #define MSI_IOVA_LENGTH 0x100000 +/* Interconnect bandwidth vote values for the SMMU register access path */ +#define ARM_SMMU_ICC_AVG_BW 0 +#define ARM_SMMU_ICC_PEAK_BW_HIGH 1000 +#define ARM_SMMU_ICC_PEAK_BW_LOW 0 + static int force_stage; module_param(force_stage, int, S_IRUGO); MODULE_PARM_DESC(force_stage, @@ -86,6 +91,36 @@ static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) } } +static int arm_smmu_icc_get(struct arm_smmu_device *smmu) +{ + smmu->icc_path = devm_of_icc_get(smmu->dev, NULL); + if (IS_ERR(smmu->icc_path)) { + int err = PTR_ERR(smmu->icc_path); + + if (err == -ENODEV) { + smmu->icc_path = NULL; + return 0; + } + return dev_err_probe(smmu->dev, err, + "failed to get interconnect path\n"); + } + return 0; +} + +static void arm_smmu_icc_enable(struct arm_smmu_device *smmu) +{ + if (smmu->icc_path) + WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW, + ARM_SMMU_ICC_PEAK_BW_HIGH)); +} + +static void arm_smmu_icc_disable(struct arm_smmu_device *smmu) +{ + if (smmu->icc_path) + WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW, + ARM_SMMU_ICC_PEAK_BW_LOW)); +} + static void arm_smmu_rpm_use_autosuspend(struct arm_smmu_device *smmu) { /* @@ -2212,6 +2247,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (err) return err; + /* + * Acquire and vote the interconnect path before accessing any SMMU + * registers (including ARM_SMMU_GR0_ID0 in arm_smmu_device_cfg_probe). + */ + err = arm_smmu_icc_get(smmu); + if (err) { + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + return err; + } + arm_smmu_icc_enable(smmu); + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2291,8 +2337,10 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) if (pm_runtime_enabled(smmu->dev)) pm_runtime_force_suspend(smmu->dev); - else + else { clk_bulk_disable(smmu->num_clks, smmu->clks); + arm_smmu_icc_disable(smmu); + } clk_bulk_unprepare(smmu->num_clks, smmu->clks); } @@ -2312,9 +2360,13 @@ static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); int ret; + arm_smmu_icc_enable(smmu); + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); - if (ret) + if (ret) { + arm_smmu_icc_disable(smmu); return ret; + } arm_smmu_device_reset(smmu); @@ -2326,6 +2378,7 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); clk_bulk_disable(smmu->num_clks, smmu->clks); + arm_smmu_icc_disable(smmu); return 0; } diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h index 26d2e33cd328b..c00606a416b2f 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -335,6 +336,7 @@ struct arm_smmu_device { int num_clks; unsigned int *irqs; struct clk_bulk_data *clks; + struct icc_path *icc_path; spinlock_t global_sync_lock; From f3d01571883a5ae69c0ce46227df68b535b274f1 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:04 +0530 Subject: [PATCH 0423/1058] FROMLIST: arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU On Kodiak platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-3-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..eefa4b836a813 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3386,6 +3386,8 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; gfx_0_tbu: tbu@3dd9000 { From 2944e2ea5c573b64e7eb074a42d881d57ac04a51 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:05 +0530 Subject: [PATCH 0424/1058] FROMLIST: arm64: dts: qcom: lemans: Add GEM_NOC interconnect for adreno SMMU On Lemans platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-4-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb..1bddf6efd47be 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4796,6 +4796,8 @@ , , ; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; serdes0: phy@8901000 { From 17dff83c3f13c7828243466ded58d75bdce88a18 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:06 +0530 Subject: [PATCH 0425/1058] FROMLIST: arm64: dts: qcom: monaco: Add GEM_NOC interconnect for adreno SMMU On Monaco platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-5-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/monaco.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bd..b7e9f66688c98 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -5088,6 +5088,8 @@ "gpu_cc_hub_aon_clk"; power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; pmu@9091000 { From eb8dd079d136d8964af5e3b4fb4b9f6373c88e0b Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:12:07 +0530 Subject: [PATCH 0426/1058] FROMLIST: arm64: dts: qcom: talos: Add GEM_NOC interconnect for adreno SMMU On Talos platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-6-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/talos.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index fb1bbc51bb8a4..74322507f4e8c 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -2090,6 +2090,8 @@ "iface"; power-domains = <&gpucc CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; stm@6002000 { From 44df12a52b9e962122cf7f6253ca1d6d3f2da862 Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Wed, 17 Jun 2026 03:06:14 +0530 Subject: [PATCH 0427/1058] FROMLIST: swiotlb: introduce Kconfig option for compile-time default pool size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SWIOTLB bounce buffer pool size is hardcoded at 64 MB via IO_TLB_DEFAULT_SIZE with no compile-time knob to adjust it. On memory-constrained embedded or mobile platforms equipped with a hardware IOMMU (e.g., ARM SMMU) covering most DMA-capable devices, reserving 64 MB at boot is unnecessarily wasteful — the SWIOTLB is only exercised for devices that bypass the IOMMU or have restricted DMA address ranges. Introduce CONFIG_SWIOTLB_DEFAULT_SIZE_MB, an integer Kconfig option (range 1–64 MB, default 64) that allows platforms to set a smaller compile-time default. IO_TLB_DEFAULT_SIZE is updated to derive from this value when CONFIG_SWIOTLB is enabled, preserving the existing 64 MB default when the option is not configured. The runtime "swiotlb=" kernel parameter override remains fully supported and takes precedence over the compile-time default. Link: https://lore.kernel.org/all/20260617-swiotlb-v1-1-abfee3faf4ea@oss.qualcomm.com/ Signed-off-by: Jagadeesh Pagadala Signed-off-by: Bibek Kumar Patro --- include/linux/swiotlb.h | 8 ++++++-- kernel/dma/Kconfig | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 3dae0f592063e..1665a9ce8f941 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -32,8 +32,12 @@ struct scatterlist; #define IO_TLB_SHIFT 11 #define IO_TLB_SIZE (1 << IO_TLB_SHIFT) -/* default to 64MB */ -#define IO_TLB_DEFAULT_SIZE (64UL<<20) +/* compile-time default; overridable via CONFIG_SWIOTLB_DEFAULT_SIZE_MB */ +#ifdef CONFIG_SWIOTLB +#define IO_TLB_DEFAULT_SIZE ((unsigned long)CONFIG_SWIOTLB_DEFAULT_SIZE_MB << 20) +#else +#define IO_TLB_DEFAULT_SIZE (64UL << 20) +#endif unsigned long swiotlb_size_or_default(void); void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig index 0a4ba21a57a7c..3830a63ae032d 100644 --- a/kernel/dma/Kconfig +++ b/kernel/dma/Kconfig @@ -86,6 +86,28 @@ config SWIOTLB bool select NEED_DMA_MAP_STATE +config SWIOTLB_DEFAULT_SIZE_MB + int "Default SWIOTLB bounce buffer size in MB" + depends on SWIOTLB + range 1 64 + default 64 + help + Sets the default size of the software IO TLB (SWIOTLB) bounce buffer + pool allocated at boot time. The default is 64 MB. + + On memory-constrained embedded or mobile platforms (e.g., those with + a hardware IOMMU such as ARM SMMU covering most DMA-capable devices), + a smaller value such as 4 or 8 MB may be sufficient. The SWIOTLB is + then only needed for devices that bypass the IOMMU or have restricted + DMA address ranges. + + The minimum allowed value is 1 MB. This compile-time default can be + overridden at runtime using the "swiotlb=" kernel command line + parameter. Refer to Documentation/admin-guide/kernel-parameters.txt + for details. + + If unsure, leave at the default value of 64. + config SWIOTLB_DYNAMIC bool "Dynamic allocation of DMA bounce buffers" default n From b49adaec605af7d0e4eb35e820b29d3151ca57cf Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 26 Mar 2026 00:42:59 +0530 Subject: [PATCH 0428/1058] FROMLIST: remoteproc: qcom: pas: Fix the dtb PAS context creation DTB PAS context creation should be done only for subsystems that support a DTB firmware binary; otherwise, memory is wasted. Move the context creation to the appropriate location and, while at it, fix the place where the DTB PAS context was being released unconditionally. Link: https://lore.kernel.org/lkml/20260325191301.164579-1-mukesh.ojha@oss.qualcomm.com/ Fixes: b13d8baf5601 ("remoteproc: pas: Replace metadata context with PAS context structure") Signed-off-by: Mukesh Ojha --- drivers/remoteproc/qcom_q6v5_pas.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 808e9609988d3..573339e10af23 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -247,7 +247,9 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) return 0; release_dtb_metadata: - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + if (pas->dtb_pas_id) + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + release_firmware(pas->dtb_firmware); return ret; @@ -620,6 +622,7 @@ static void qcom_pas_pds_detach(struct qcom_pas *pas, struct device **pds, size_ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) { + struct rproc *rproc = pas->rproc; struct resource res; int ret; @@ -637,6 +640,12 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) return PTR_ERR(pas->mem_region); } + pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id, + pas->mem_phys, pas->mem_size); + if (IS_ERR(pas->pas_ctx)) + return PTR_ERR(pas->pas_ctx); + + pas->pas_ctx->use_tzmem = rproc->has_iommu; if (!pas->dtb_pas_id) return 0; @@ -654,6 +663,14 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) return PTR_ERR(pas->dtb_mem_region); } + pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id, + pas->dtb_mem_phys, + pas->dtb_mem_size); + if (IS_ERR(pas->dtb_pas_ctx)) + return PTR_ERR(pas->dtb_pas_ctx); + + pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; + return 0; } From 0d79c0a6a104f642bdc50f544d5ae9cbfacfb526 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 10 Mar 2026 19:22:05 +0530 Subject: [PATCH 0429/1058] FROMLIST: remoteproc: qcom: pas: Map/unmap subsystem region before auth_and_reset Qualcomm remoteproc drivers such as qcom_q6v5_mss, which do not use the Peripheral Authentication Service (PAS), always map the MBA region before use and unmap it once the usage is complete. This behavior was introduced to avoid issues seen in the past where speculative accesses from the application processor to the MBA region after it was assigned to the remote Q6 led to an XPU violation. The issue was mitigated by unmapping the region before handing control to the remote Q6. Currently, most Qualcomm SoCs using the PAS driver run either with a standalone QHEE or the Gunyah hypervisor. In these environments, the hypervisor unmaps the Q6 memory from HLOS Stage-2 and remaps it into the Q6 Stage-2 page table. As a result, speculative accesses from HLOS cannot reach the region even if it remains mapped in HLOS Stage-1; therefore, XPU violations cannot occur. However, when the same SoC runs Linux at EL2, Linux itself must perform the unmapping to avoid such issues. It is still correct to apply this mapping/ unmapping sequence even for SoCs that run under Gunyah, so this behavior should not be conditional. Link: https://lore.kernel.org/lkml/20260325191301.164579-2-mukesh.ojha@oss.qualcomm.com/ Signed-off-by: Mukesh Ojha --- drivers/remoteproc/qcom_q6v5_pas.c | 40 ++++++++++++++++++++--------- drivers/soc/qcom/mdt_loader.c | 18 ++++++++++--- include/linux/soc/qcom/mdt_loader.h | 4 +-- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 573339e10af23..6d82626a12358 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -145,7 +145,16 @@ static void qcom_pas_minidump(struct rproc *rproc) if (rproc->dump_conf == RPROC_COREDUMP_DISABLED) return; + pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size); + if (!pas->mem_region) { + dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", + &pas->mem_phys, pas->mem_size); + return; + } + qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump); + iounmap(pas->mem_region); + pas->mem_region = NULL; } static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds, @@ -238,7 +247,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) } ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, - pas->dtb_firmware_name, pas->dtb_mem_region, + pas->dtb_firmware_name, &pas->dtb_mem_reloc); if (ret) goto release_dtb_metadata; @@ -318,7 +327,7 @@ static int qcom_pas_start(struct rproc *rproc) } ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware, - pas->mem_region, &pas->mem_reloc); + &pas->mem_reloc); if (ret) goto release_pas_metadata; @@ -509,6 +518,22 @@ static unsigned long qcom_pas_panic(struct rproc *rproc) return qcom_q6v5_panic(&pas->q6v5); } +static void qcom_pas_coredump(struct rproc *rproc) +{ + struct qcom_pas *pas = rproc->priv; + + pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size); + if (!pas->mem_region) { + dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", + &pas->mem_phys, pas->mem_size); + return; + } + + rproc_coredump(rproc); + iounmap(pas->mem_region); + pas->mem_region = NULL; +} + static const struct rproc_ops qcom_pas_ops = { .unprepare = qcom_pas_unprepare, .start = qcom_pas_start, @@ -517,6 +542,7 @@ static const struct rproc_ops qcom_pas_ops = { .parse_fw = qcom_pas_parse_firmware, .load = qcom_pas_load, .panic = qcom_pas_panic, + .coredump = qcom_pas_coredump, }; static const struct rproc_ops qcom_pas_minidump_ops = { @@ -634,11 +660,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->mem_phys = pas->mem_reloc = res.start; pas->mem_size = resource_size(&res); - pas->mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->mem_region)) { - dev_err(pas->dev, "unable to map memory region: %pR\n", &res); - return PTR_ERR(pas->mem_region); - } pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id, pas->mem_phys, pas->mem_size); @@ -657,11 +678,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->dtb_mem_phys = pas->dtb_mem_reloc = res.start; pas->dtb_mem_size = resource_size(&res); - pas->dtb_mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->dtb_mem_region)) { - dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res); - return PTR_ERR(pas->dtb_mem_region); - } pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id, pas->dtb_mem_phys, diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index c004d444d6985..33f3543f8e558 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -478,22 +479,31 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * @ctx: Pointer to the PAS (Peripheral Authentication Service) context * @fw: Firmware object representing the .mdt file * @firmware: Name of the firmware used to construct segment file names - * @mem_region: Memory region allocated for loading the firmware * @reloc_base: Physical address adjusted after relocation * * Return: 0 on success or a negative error code on failure. */ int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base) + const char *firmware, phys_addr_t *reloc_base) { + void *mem_region; int ret; ret = __qcom_mdt_pas_init(ctx->dev, fw, firmware, ctx->pas_id, ctx->mem_phys, ctx); if (ret) return ret; - return qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, - ctx->mem_size, reloc_base); + mem_region = ioremap_wc(ctx->mem_phys, ctx->mem_size); + if (!mem_region) { + dev_err(ctx->dev, "unable to map memory region: %pa+%zx\n", &ctx->mem_phys, + ctx->mem_size); + return -EINVAL; + } + + ret = qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, + ctx->mem_size, reloc_base); + iounmap(mem_region); + return ret; } EXPORT_SYMBOL_GPL(qcom_mdt_pas_load); diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h index 82372e0db0a18..7c551b98e1822 100644 --- a/include/linux/soc/qcom/mdt_loader.h +++ b/include/linux/soc/qcom/mdt_loader.h @@ -21,7 +21,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t *reloc_base); int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base); + const char *firmware, phys_addr_t *reloc_base); int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, const char *fw_name, void *mem_region, @@ -47,7 +47,7 @@ static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, static inline int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, const char *firmware, - void *mem_region, phys_addr_t *reloc_base) + phys_addr_t *reloc_base) { return -ENODEV; } From 79a5b57b4973a0258eb008fc92c4fbf81ac8579a Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 26 Mar 2026 00:43:01 +0530 Subject: [PATCH 0430/1058] FROMLIST: remoteproc: qcom: pas: Drop unused dtb_mem_region field dtb_mem_region is no longer referenced after the ioremap was moved to respective places where mapping is required. Remove it from struct qcom_pas. Link: https://lore.kernel.org/lkml/20260325191301.164579-3-mukesh.ojha@oss.qualcomm.com/ Signed-off-by: Mukesh Ojha --- drivers/remoteproc/qcom_q6v5_pas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 6d82626a12358..7bf99d3d59cb2 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -97,8 +97,9 @@ struct qcom_pas { phys_addr_t mem_reloc; phys_addr_t dtb_mem_reloc; phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT]; + void *mem_region; - void *dtb_mem_region; + size_t mem_size; size_t dtb_mem_size; size_t region_assign_size[MAX_ASSIGN_COUNT]; From f0dccce058e75f5ea49b0eb129e9b58a9e14705e Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 9 Apr 2026 01:52:24 -0700 Subject: [PATCH 0431/1058] FROMLIST: dt-bindings: remoteproc: qcom: cleanup qcom,adsp.yaml Items in qcom,adsp.yaml has common clock and interrupt properties, move these out of the allOf section to avoid list the compatible repeatly. Link: https://lore.kernel.org/lkml/20260409-knp-soccp-v5-1-805a492124da@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang --- .../bindings/remoteproc/qcom,adsp.yaml | 64 ++++--------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 16a245fe2738d..a270834605da2 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -32,6 +32,14 @@ properties: reg: maxItems: 1 + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + cx-supply: true px-supply: @@ -49,6 +57,12 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + maxItems: 5 + + interrupt-names: + maxItems: 5 + required: - compatible - memory-region @@ -57,56 +71,6 @@ unevaluatedProperties: false allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - clocks: - items: - - description: XO clock - clock-names: - items: - - const: xo - - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - interrupts: - maxItems: 5 - interrupt-names: - maxItems: 5 - - if: properties: compatible: From 7efa8c31c33d7629cf478b4e07a41574d1a34a97 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 9 Apr 2026 01:52:25 -0700 Subject: [PATCH 0432/1058] FROMLIST: dt-bindings: remoteproc: qcom: move interrupts and interrupt-names list out of pas-common Move interrupts and interrupt-names list out of pas-common since they will be redefined differently for Kaanapali SoCCP. Link: https://lore.kernel.org/lkml/20260409-knp-soccp-v5-2-805a492124da@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang --- .../bindings/remoteproc/qcom,adsp.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,milos-pas.yaml | 18 +++++++++++++---- .../bindings/remoteproc/qcom,pas-common.yaml | 16 ++------------- .../bindings/remoteproc/qcom,qcs404-pas.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,sa8775p-pas.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,sc7180-pas.yaml | 20 +++++++++++++++++++ .../remoteproc/qcom,sc8280xp-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sdx55-pas.yaml | 16 +++++++++++++-- .../bindings/remoteproc/qcom,sm6115-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm6350-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm6375-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8150-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8350-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8550-pas.yaml | 20 +++++++++++++++++++ 14 files changed, 226 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index a270834605da2..16c35e15ee1b4 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -58,10 +58,20 @@ properties: description: Firmware name for the Hexagon core interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack required: - compatible diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index e5cce0d05fc69..d22d50c1e1ea3 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -34,12 +34,22 @@ properties: - const: xo interrupts: - minItems: 6 - maxItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 - maxItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack qcom,qmp: $ref: /schemas/types.yaml#/definitions/phandle diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 4607b459131b4..3847aadfa9807 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -26,23 +26,11 @@ properties: interrupts: minItems: 5 - items: - - description: Watchdog interrupt - - description: Fatal interrupt - - description: Ready interrupt - - description: Handover interrupt - - description: Stop acknowledge interrupt - - description: Shutdown acknowledge interrupt + maxItems: 6 interrupt-names: minItems: 5 - items: - - const: wdog - - const: fatal - - const: ready - - const: handover - - const: stop-ack - - const: shutdown-ack + maxItems: 6 iommus: maxItems: 1 diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index ad45fd00ae346..5854b3d2041d5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -32,10 +32,20 @@ properties: - const: xo interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack power-domains: false power-domain-names: false diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index bcd2bcf96e246..7f287e55896e5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -59,10 +59,20 @@ properties: - description: Memory region for main Firmware authentication interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack required: - compatible diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index 66b455d0a8e32..cb0a61fc301df 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -48,6 +48,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index 8227527c1d770..fef9d7c39f3c5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -45,6 +45,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index 8c4abde749150..2bbd427c6ea49 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -30,10 +30,22 @@ properties: - const: xo interrupts: - minItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack power-domains: items: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index eeb6a8aafeb92..987fac433fae5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -51,6 +51,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index c1a3cc308bdb2..53ffb1ccd1995 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -45,6 +45,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml index 7286b2baa19f2..6823a2a8d74e7 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml @@ -39,6 +39,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + smd-edge: false required: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index a8cddf7e2fe1a..8a1fae095a3bd 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -61,6 +61,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 6d09823153fc8..4ea7518db5374 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -55,6 +55,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 9f30a38152a38..4721c04ce09b4 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -75,6 +75,26 @@ properties: - description: DSM Memory region 2 - description: Memory region for Qlink Logging + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg From 3d60ac082d5f717bee86a4f294465485eaef54ac Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 9 Apr 2026 01:52:26 -0700 Subject: [PATCH 0433/1058] FROMLIST: dt-bindings: remoteproc: qcom: Document pas for SoCCP on Kaanapali and Glymur platforms Document the component used to boot SoCCP on Kaanapali SoC and add compatible for Glymur SoCCP which could fallback to Kaanapali. Extend the "qcom,smem-states", "qcom,smem-state-names" in the pas-common and add maxItems constraints for SMEM properties in the documents that reference to pas-common. Link: https://lore.kernel.org/lkml/20260409-knp-soccp-v5-3-805a492124da@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang --- .../bindings/remoteproc/qcom,adsp.yaml | 8 + .../remoteproc/qcom,kaanapali-soccp-pas.yaml | 154 ++++++++++++++++++ .../bindings/remoteproc/qcom,milos-pas.yaml | 8 + .../bindings/remoteproc/qcom,pas-common.yaml | 6 +- .../bindings/remoteproc/qcom,qcs404-pas.yaml | 8 + .../bindings/remoteproc/qcom,sa8775p-pas.yaml | 8 + .../bindings/remoteproc/qcom,sc7180-pas.yaml | 8 + .../remoteproc/qcom,sc8280xp-pas.yaml | 8 + .../bindings/remoteproc/qcom,sdx55-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6115-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6350-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6375-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8150-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8350-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8550-pas.yaml | 8 + 15 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 16c35e15ee1b4..7e8ecae8e6cb6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -73,6 +73,14 @@ properties: - const: handover - const: stop-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - memory-region diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml new file mode 100644 index 0000000000000..ce18460a949fc --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,kaanapali-soccp-pas.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali SoCCP Peripheral Authentication Service + +maintainers: + - Jingyi Wang + +description: + The SoC Control Processor (SoCCP) is a small RISC-V MCU that controls USB + Type-C, battery charging and various other functions on Qualcomm SoCs, somewhat + analogous to traditional PC Embedded Controllers. This document describes + the Peripheral Authentication Service that loads and boots firmware for SoCCP. + +properties: + compatible: + oneOf: + - items: + - enum: + - qcom,glymur-soccp-pas + - const: qcom,kaanapali-soccp-pas + - enum: + - qcom,kaanapali-soccp-pas + + reg: + maxItems: 1 + + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + + power-domains: + items: + - description: CX power domain + - description: MX power domain + + power-domain-names: + items: + - const: cx + - const: mx + + firmware-name: + items: + - description: Firmware name of the SoC Control Processor + - description: Firmware name of the SoCCP Devicetree + + memory-region: + items: + - description: Memory region for main Firmware authentication + - description: Memory region for Devicetree Firmware authentication + + interrupts: + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Pong interrupt + + interrupt-names: + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: pong + + qcom,smem-states: + minItems: 2 + description: States used by the AP to signal the SoC Control Processor + + qcom,smem-state-names: + minItems: 2 + description: The names of the state bits used for SMP2P output + +required: + - compatible + - reg + - memory-region + - power-domains + - power-domain-names + +allOf: + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #define IPCC_MPROC_SOCCP + + remoteproc@d00000 { + compatible = "qcom,kaanapali-soccp-pas"; + reg = <0x00d00000 0x200000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem_mem>; + + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + qcom,smem-states = <&soccp_smp2p_out 0>, + <&soccp_smp2p_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "soccp"; + qcom,remote-pid = <19>; + + /* ... */ + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index d22d50c1e1ea3..99d7337e58ec5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -69,6 +69,14 @@ properties: - description: Memory region for core Firmware authentication - description: Memory region for Devicetree Firmware authentication + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 3847aadfa9807..4876a99b61de5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -46,19 +46,23 @@ properties: qcom,smem-states: $ref: /schemas/types.yaml#/definitions/phandle-array description: States used by the AP to signal the Hexagon core + minItems: 1 items: - - description: Stop the modem + - description: Stop the remoteproc items: - description: Phandle to the Shared Memory Point 2 Point device handling the communication with a remote processor - description: Single bit index to toggle in the value sent to the remote processor maximum: 32 + - description: ping the remoteproc qcom,smem-state-names: description: The names of the state bits used for SMP2P output + minItems: 1 items: - const: stop + - const: ping smd-edge: $ref: /schemas/remoteproc/qcom,smd-edge.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index 5854b3d2041d5..bf9bf1af9ff14 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -59,6 +59,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index 7f287e55896e5..dda2d144b7206 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -74,6 +74,14 @@ properties: - const: handover - const: stop-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index cb0a61fc301df..b20780e5e26bd 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -68,6 +68,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index fef9d7c39f3c5..4bbe4a986c7c5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -65,6 +65,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index 2bbd427c6ea49..8c16b01c53e42 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -71,6 +71,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index 987fac433fae5..454ba82bd6f18 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -71,6 +71,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index 53ffb1ccd1995..42e02c64347a0 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -65,6 +65,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml index 6823a2a8d74e7..274f87880e2e6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml @@ -61,6 +61,14 @@ properties: smd-edge: false + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index 8a1fae095a3bd..5a7c5f8c92d17 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -81,6 +81,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 4ea7518db5374..72d0db5698c5c 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -75,6 +75,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 4721c04ce09b4..faf7b2890de8d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -95,6 +95,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg From 9e6668fd303e73d4b38137b5664083c1cf15dcbe Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 9 Apr 2026 01:52:27 -0700 Subject: [PATCH 0434/1058] FROMLIST: remoteproc: qcom: pas: Add late attach support for subsystems Subsystems can be brought out of reset by entities such as bootloaders. As the irq enablement could be later than subsystem bring up, the state of subsystem should be checked by reading SMP2P bits and performing ping test. A new qcom_pas_attach() function is introduced. if a crash state is detected for the subsystem, rproc_report_crash() is called. If the subsystem is ready and the ping is successful, it will be marked as "attached". If ready irq is not received, it could be the early boot feature is not supported by other entities. In this case, the state will be marked as RPROC_OFFLINE so that the PAS driver can load the firmware and start the remoteproc. Link: https://lore.kernel.org/lkml/20260409-knp-soccp-v5-4-805a492124da@oss.qualcomm.com/ Co-developed-by: Gokul Krishna Krishnakumar Signed-off-by: Gokul Krishna Krishnakumar Signed-off-by: Jingyi Wang --- drivers/remoteproc/qcom_q6v5.c | 69 ++++++++++++++++++++++++++ drivers/remoteproc/qcom_q6v5.h | 6 +++ drivers/remoteproc/qcom_q6v5_pas.c | 80 ++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 58d5b85e58cda..52247c17c38ac 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -20,6 +20,7 @@ #define Q6V5_LOAD_STATE_MSG_LEN 64 #define Q6V5_PANIC_DELAY_MS 200 +#define Q6V5_PING_TIMEOUT_MS 500 static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable) { @@ -234,6 +235,74 @@ unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5) } EXPORT_SYMBOL_GPL(qcom_q6v5_panic); +static irqreturn_t q6v5_pong_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + complete(&q6v5->ping_done); + + return IRQ_HANDLED; +} + +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5) +{ + int ret; + int ping_failed = 0; + + reinit_completion(&q6v5->ping_done); + + /* Set master kernel Ping bit */ + ret = qcom_smem_state_update_bits(q6v5->ping_state, + BIT(q6v5->ping_bit), BIT(q6v5->ping_bit)); + if (ret) { + dev_err(q6v5->dev, "Failed to update ping bits\n"); + return ret; + } + + ret = wait_for_completion_timeout(&q6v5->ping_done, msecs_to_jiffies(Q6V5_PING_TIMEOUT_MS)); + if (!ret) { + ping_failed = -ETIMEDOUT; + dev_err(q6v5->dev, "Failed to get back pong\n"); + } + + /* Clear ping bit master kernel */ + ret = qcom_smem_state_update_bits(q6v5->ping_state, BIT(q6v5->ping_bit), 0); + if (ret) { + dev_err(q6v5->dev, "Failed to clear master kernel bits\n"); + return ret; + } + + return ping_failed; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem); + +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev) +{ + int ret = -ENODEV; + + q6v5->ping_state = devm_qcom_smem_state_get(&pdev->dev, "ping", &q6v5->ping_bit); + if (IS_ERR(q6v5->ping_state)) { + dev_err(&pdev->dev, "Failed to acquire smem state %ld\n", + PTR_ERR(q6v5->ping_state)); + return PTR_ERR(q6v5->ping_state); + } + + init_completion(&q6v5->ping_done); + + q6v5->pong_irq = platform_get_irq_byname(pdev, "pong"); + if (q6v5->pong_irq < 0) + return q6v5->pong_irq; + + ret = devm_request_threaded_irq(&pdev->dev, q6v5->pong_irq, NULL, + q6v5_pong_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 pong", q6v5); + if (ret) + dev_err(&pdev->dev, "Failed to acquire pong IRQ\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem_init); + /** * qcom_q6v5_init() - initializer of the q6v5 common struct * @q6v5: handle to be initialized diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 5a859c41896e9..5025ffc4dbe80 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -17,22 +17,26 @@ struct qcom_q6v5 { struct rproc *rproc; struct qcom_smem_state *state; + struct qcom_smem_state *ping_state; struct qmp *qmp; struct icc_path *path; unsigned stop_bit; + unsigned int ping_bit; int wdog_irq; int fatal_irq; int ready_irq; int handover_irq; int stop_irq; + int pong_irq; bool handover_issued; struct completion start_done; struct completion stop_done; + struct completion ping_done; int crash_reason; @@ -52,5 +56,7 @@ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon); int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev); #endif diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 7bf99d3d59cb2..d3fd024d92e80 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -60,6 +60,7 @@ struct qcom_pas_data { int region_assign_count; bool region_assign_shared; int region_assign_vmid; + bool early_boot; }; struct qcom_pas { @@ -432,9 +433,15 @@ static int qcom_pas_stop(struct rproc *rproc) qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); - handover = qcom_q6v5_unprepare(&pas->q6v5); - if (handover) - qcom_pas_handover(&pas->q6v5); + /* + * qcom_q6v5_prepare is not called in qcom_pas_attach, skip unprepare to + * avoid mismatch. + */ + if (pas->rproc->state != RPROC_ATTACHED) { + handover = qcom_q6v5_unprepare(&pas->q6v5); + if (handover) + qcom_pas_handover(&pas->q6v5); + } if (pas->smem_host_id) ret = qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id); @@ -535,6 +542,63 @@ static void qcom_pas_coredump(struct rproc *rproc) pas->mem_region = NULL; } +static int qcom_pas_attach(struct rproc *rproc) +{ + int ret; + struct qcom_pas *pas = rproc->priv; + bool ready_state; + bool crash_state; + + pas->q6v5.running = true; + ret = irq_get_irqchip_state(pas->q6v5.fatal_irq, + IRQCHIP_STATE_LINE_LEVEL, &crash_state); + + if (ret) + goto disable_running; + + if (crash_state) { + dev_err(pas->dev, "Subsystem has crashed before driver probe\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + ret = -EINVAL; + goto disable_running; + } + + ret = irq_get_irqchip_state(pas->q6v5.ready_irq, + IRQCHIP_STATE_LINE_LEVEL, &ready_state); + + if (ret) + goto disable_running; + + if (unlikely(!ready_state)) { + /* + * The bootloader may not support early boot, mark the state as + * RPROC_OFFLINE so that the PAS driver can load the firmware and + * start the remoteproc. + */ + dev_err(pas->dev, "Failed to get subsystem ready interrupt\n"); + pas->rproc->state = RPROC_OFFLINE; + ret = -EINVAL; + goto disable_running; + } + + ret = qcom_q6v5_ping_subsystem(&pas->q6v5); + + if (ret) { + dev_err(pas->dev, "Failed to ping subsystem, assuming device crashed\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + goto disable_running; + } + + pas->q6v5.handover_issued = true; + + return 0; + +disable_running: + pas->q6v5.running = false; + + return ret; +} + static const struct rproc_ops qcom_pas_ops = { .unprepare = qcom_pas_unprepare, .start = qcom_pas_start, @@ -544,6 +608,7 @@ static const struct rproc_ops qcom_pas_ops = { .load = qcom_pas_load, .panic = qcom_pas_panic, .coredump = qcom_pas_coredump, + .attach = qcom_pas_attach, }; static const struct rproc_ops qcom_pas_minidump_ops = { @@ -886,6 +951,15 @@ static int qcom_pas_probe(struct platform_device *pdev) pas->pas_ctx->use_tzmem = rproc->has_iommu; pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; + + if (desc->early_boot) { + ret = qcom_q6v5_ping_subsystem_init(&pas->q6v5, pdev); + if (ret) + dev_warn(&pdev->dev, "Falling back to firmware load\n"); + else + pas->rproc->state = RPROC_DETACHED; + } + ret = rproc_add(rproc); if (ret) goto remove_ssr_sysmon; From ce284eea5fbde6dd880cb8e90df6b044a01d0256 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Thu, 9 Apr 2026 01:52:28 -0700 Subject: [PATCH 0435/1058] FROMLIST: remoteproc: qcom_q6v5_pas: Add SoCCP node on Kaanapali The SoC Control Processor (SoCCP) is small RISC-V MCU that controls USB Type-C, battery charging and various other functions on Qualcomm SoCs. It provides a solution for control-plane processing, reducing per-subsystem microcontroller reinvention. Add support for SoCCP PAS loader on Kaanapali platform. Link: https://lore.kernel.org/lkml/20260409-knp-soccp-v5-5-805a492124da@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Jingyi Wang Reviewed-by: Bartosz Golaszewski --- drivers/remoteproc/qcom_q6v5_pas.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index d3fd024d92e80..60d9c900512cf 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1680,8 +1680,26 @@ static const struct qcom_pas_data sm8750_mpss_resource = { .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, }; +static const struct qcom_pas_data kaanapali_soccp_resource = { + .crash_reason_smem = 656, + .firmware_name = "soccp.mbn", + .dtb_firmware_name = "soccp_dtb.mbn", + .pas_id = 51, + .dtb_pas_id = 0x41, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .ssr_name = "soccp", + .sysmon_name = "soccp", + .auto_boot = true, + .early_boot = true, +}; + static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,eliza-adsp-pas", .data = &sm8550_adsp_resource }, + { .compatible = "qcom,kaanapali-soccp-pas", .data = &kaanapali_soccp_resource }, { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource }, { .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource }, { .compatible = "qcom,milos-mpss-pas", .data = &sm8450_mpss_resource }, From 17eed33101ba246bdd3b3594a8f3ceba61f25f6b Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Mon, 23 Mar 2026 12:38:52 +0530 Subject: [PATCH 0436/1058] FROMLIST: dt-bindings: display: bridge: lontium,lt9211: Add lt9211c support Add binding for the Lontium LT9211C bridge chip. Signed-off-by: Yi Zhang Signed-off-by: Nilesh Laad Signed-off-by: Gopi Botlagunta Link: https://lore.kernel.org/all/20260323-add-lt9211c-bridge-v5-1-9c63bb035c17@oss.qualcomm.com/ --- .../devicetree/bindings/display/bridge/lontium,lt9211.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml index 7cfe92a8bcd72..de61bda09db96 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml @@ -4,19 +4,20 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9211.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9211 DSI/LVDS/DPI to DSI/LVDS/DPI bridge. +title: Lontium LT9211/LT9211C DSI/LVDS/DPI to DSI/LVDS/DPI bridge. maintainers: - Marek Vasut description: | - The LT9211 are bridge devices which convert Single/Dual-Link DSI/LVDS + The LT9211 and LT9211C are bridge devices which convert Single/Dual-Link DSI/LVDS or Single DPI to Single/Dual-Link DSI/LVDS or Single DPI. properties: compatible: enum: - lontium,lt9211 + - lontium,lt9211c reg: maxItems: 1 From 81275a8e370616e01ef67e4fd3a8b24166cce7bb Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 28 Jan 2026 18:28:20 +0530 Subject: [PATCH 0437/1058] FROMLIST: drm/bridge: lt9611uxc: reset edid_read on disconnect Currently edid_read has value from previous connect session and resulting in drm using older edid before new edid is available in lt9611uxc. Reset edid_read so that correct status is updated and correct edid is available for drm. Link: https://lore.kernel.org/lkml/20260202-lt9611uxc-reset-edid-v2-1-b1e1d72edc90@oss.qualcomm.com/ Signed-off-by: Ravi Agola Signed-off-by: Nilesh Laad --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 9427cc2358ae1..2e59318ccf2ba 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -169,6 +169,9 @@ static void lt9611uxc_hpd_work(struct work_struct *work) connected = lt9611uxc->hdmi_connected; mutex_unlock(<9611uxc->ocm_lock); + if (!connected) + lt9611uxc->edid_read = false; + drm_bridge_hpd_notify(<9611uxc->bridge, connected ? connector_status_connected : From b72d7c62bea408902084d2533c9829c41c199f55 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 23 Mar 2026 19:36:04 +0800 Subject: [PATCH 0438/1058] FROMLIST: drm/bridge: display-connector: don't autoenable HPD IRQ If HPD IRQ is enabled in the display_connector's probe, it can be triggered too early, before the DRM connector is completely setup. Use the enable_hpd / disable_hpd callbacks to control enablement of the HPD IRQ. Fixes: 0c275c30176b ("drm/bridge: Add bridge driver for display connectors") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260314-dp-connector-hpd-v1-1-786044cedc17@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/display-connector.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c index 16c0631adeb18..6bb1134f75c3d 100644 --- a/drivers/gpu/drm/bridge/display-connector.c +++ b/drivers/gpu/drm/bridge/display-connector.c @@ -87,6 +87,20 @@ display_connector_bridge_detect(struct drm_bridge *bridge, struct drm_connector return display_connector_detect(bridge); } +static void display_connector_hpd_enable(struct drm_bridge *bridge) +{ + struct display_connector *conn = to_display_connector(bridge); + + enable_irq(conn->hpd_irq); +} + +static void display_connector_hpd_disable(struct drm_bridge *bridge) +{ + struct display_connector *conn = to_display_connector(bridge); + + disable_irq(conn->hpd_irq); +} + static const struct drm_edid *display_connector_edid_read(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -178,6 +192,8 @@ static u32 *display_connector_get_input_bus_fmts(struct drm_bridge *bridge, static const struct drm_bridge_funcs display_connector_bridge_funcs = { .attach = display_connector_attach, .detect = display_connector_bridge_detect, + .hpd_enable = display_connector_hpd_enable, + .hpd_disable = display_connector_hpd_disable, .edid_read = display_connector_edid_read, .atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts, .atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts, @@ -307,6 +323,7 @@ static int display_connector_probe(struct platform_device *pdev) NULL, display_connector_hpd_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_NO_AUTOEN | IRQF_ONESHOT, "HPD", conn); if (ret) { From 970ce6c67522123ce798ecd41cfa4d8b1f961f29 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 23 Mar 2026 19:37:45 +0800 Subject: [PATCH 0439/1058] FROMLIST: drm/bridge: display-connector: trigger initial HPD event for DP If the DisplayPort drivers use display-connector for the HPD detection, the internal HPD state machine might be not active and thus the hardware might be not able to handle cable detection correctly. Instead it will depend on the externall HPD notifications to set the cable state, bypassing the internal HPD state machine (for example this is the case for the msm DP driver). However if the cable has been plugged before the HPD IRQ has been enabled, there will be no HPD event coming. The drivers might fail detection in such a case. Trigger the HPD notification after enabling the HPD IRQ, propagating the cable insertion state. Fixes: 2e2bf3a5584d ("drm/bridge: display-connector: add DP support") Reported-by: Yongxing Mou Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260314-dp-connector-hpd-v1-2-786044cedc17@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/display-connector.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c index 6bb1134f75c3d..f7a5bfd9c0754 100644 --- a/drivers/gpu/drm/bridge/display-connector.c +++ b/drivers/gpu/drm/bridge/display-connector.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,8 @@ struct display_connector { struct regulator *supply; struct gpio_desc *ddc_en; + + struct work_struct hpd_work; }; static inline struct display_connector * @@ -92,15 +95,29 @@ static void display_connector_hpd_enable(struct drm_bridge *bridge) struct display_connector *conn = to_display_connector(bridge); enable_irq(conn->hpd_irq); + + if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + schedule_work(&conn->hpd_work); } static void display_connector_hpd_disable(struct drm_bridge *bridge) { struct display_connector *conn = to_display_connector(bridge); + if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + cancel_work_sync(&conn->hpd_work); + disable_irq(conn->hpd_irq); } +static void display_connector_hpd_work(struct work_struct *work) +{ + struct display_connector *conn = container_of(work, struct display_connector, hpd_work); + struct drm_bridge *bridge = &conn->bridge; + + drm_bridge_hpd_notify(bridge, display_connector_detect(bridge)); +} + static const struct drm_edid *display_connector_edid_read(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -395,6 +412,8 @@ static int display_connector_probe(struct platform_device *pdev) conn->bridge.ops |= DRM_BRIDGE_OP_DETECT; if (conn->hpd_irq >= 0) conn->bridge.ops |= DRM_BRIDGE_OP_HPD; + if (conn->hpd_irq >= 0 && type == DRM_MODE_CONNECTOR_DisplayPort) + INIT_WORK(&conn->hpd_work, display_connector_hpd_work); dev_dbg(&pdev->dev, "Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n", From cc878252328614cb5f320e8ae37819f6a7c898af Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Sun, 19 Apr 2026 15:45:56 +0530 Subject: [PATCH 0440/1058] FROMLIST: phy: qualcomm: qmp-combo: update DP PHY PLL programming on Glymur The existing DP PHY PLL and AUX configuration for the Glymur platform does not fully follow the Hardware Programming Guide requirements for DP over Type-C, which results in DP link bring-up failures. Update the DP PHY programming sequence and PLL-related register settings to align with the latest HPG recommendations. With this change, DP link training completes successfully on Glymur-based platforms. Fixes: d10736db98d2 ("phy: qualcomm: qmp-combo: Add DP offsets and settings for Glymur platforms") Link: https://lore.kernel.org/r/20260419-glymur_dp-v1-1-ad1067a8e8ae@oss.qualcomm.com Signed-off-by: Ritesh Kumar Signed-off-by: Mahadevan P --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 213 +++++++++++++----- .../qualcomm/phy-qcom-qmp-qserdes-com-v8.h | 2 + 2 files changed, 154 insertions(+), 61 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index cdcfad2e86b1d..6c5f56c2e1ffc 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -283,8 +283,8 @@ static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_DP_AON_TOGGLE_ENABLE] = QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE, [QPHY_COM_RESETSM_CNTRL] = QSERDES_V8_COM_RESETSM_CNTRL, - [QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS, - [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS, + [QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS_N3, + [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS_N3, [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN, [QPHY_DP_PHY_STATUS] = QSERDES_V8_DP_PHY_STATUS, @@ -1386,10 +1386,10 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1, 0x10), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), @@ -1404,12 +1404,13 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x56), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40), @@ -1445,26 +1446,26 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_tx_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_n3p_dp_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x1a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VMODE_CTRL1, 0x40), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT1, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT2, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCS_INTERFACE_SELECT1, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0d), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x87), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRAN_DRVR_EMP_EN, 0x5f), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x2b), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x2b), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_DRV_LVL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_DRV_LVL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x3f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x51), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x0c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10), @@ -1589,11 +1590,12 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr3[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x05), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x7a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x8d), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x27), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x83), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x37), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x54), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x06), @@ -1601,16 +1603,17 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa4), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa7), }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x04), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x21), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x08), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x46), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), @@ -1627,7 +1630,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x10), @@ -1637,9 +1641,9 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xae), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xbf), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), @@ -1647,8 +1651,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x63), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x25), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x5b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), @@ -1656,7 +1660,7 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x4f), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), @@ -1675,19 +1679,19 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYS_CLK_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x84), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x87), }; static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = { @@ -3145,6 +3149,30 @@ static int qmp_combo_configure_dp_swing(struct qmp_combo *qmp) return 0; } +static bool qmp_v8_combo_configure_dp_mode(struct qmp_combo *qmp) +{ + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; + u32 val; + + val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; + + if (dp_opts->lanes == 1 || dp_opts->lanes == 2) { + if (reverse) + val &= ~DP_PHY_PD_CTL_LANE_2_3_PWRDN; + else + val &= ~DP_PHY_PD_CTL_LANE_0_1_PWRDN; + } + + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + + writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); + + return reverse; +} + static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; @@ -3324,16 +3352,70 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp) qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); } +static int qmp_v8_helper_configure_dp_phy(struct qmp_combo *qmp) +{ + const struct qmp_phy_cfg *cfg = qmp->cfg; + u32 status; + int ret; + + writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1); + + qmp_v8_combo_configure_dp_mode(qmp); + + writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); + writel(0xa4, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); + + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); + + ret = qmp->cfg->configure_dp_clocks(qmp); + if (ret) + return ret; + + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + + writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + return 0; +} + static void qmp_v8_dp_aux_init(struct qmp_combo *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; - writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | - DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, - qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + writel(0x3f, qmp->dp_serdes + QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1); + + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, + qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); /* Turn on BIAS current for PHY/PLL */ - writel(0x1c, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); + writel(0x17, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); @@ -3361,8 +3443,8 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) writel(0x27, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); writel(0x27, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); qmp_combo_configure_dp_swing(qmp); } @@ -3370,48 +3452,41 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; - u32 phy_vco_div; unsigned long pixel_freq; - const struct qmp_phy_cfg *cfg = qmp->cfg; switch (dp_opts->link_rate) { case 1620: - phy_vco_div = 0x4; pixel_freq = 1620000000UL / 2; break; case 2700: - phy_vco_div = 0x2; pixel_freq = 2700000000UL / 2; break; case 5400: - phy_vco_div = 0x4; pixel_freq = 5400000000UL / 4; break; case 8100: - phy_vco_div = 0x3; pixel_freq = 8100000000UL / 6; break; default: /* Other link rates aren't supported */ return -EINVAL; } - writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]); /* disable core reset tsync */ writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x04, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); - writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); + writel(0x09, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); + writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_CYC); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX2_TX3_LANE_CTL); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX0_TX1_LANE_CTL); writel(0x01, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_CFG1); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN0_DRV_LVL); - writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); + writel(0x02, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000); clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq); @@ -3558,7 +3633,7 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) u32 status; int ret; - ret = qmp_v456_configure_dp_phy(qmp); + ret = qmp_v8_helper_configure_dp_phy(qmp); if (ret < 0) return ret; @@ -3570,13 +3645,13 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) } else if (dp_opts->lanes == 2) { bias0_en = reverse ? 0x3f : 0x15; bias1_en = reverse ? 0x15 : 0x3f; - drvr0_en = 0x10; - drvr1_en = 0x10; + drvr0_en = 0x30; + drvr1_en = 0x30; } else { bias0_en = 0x3f; bias1_en = 0x3f; - drvr0_en = 0x34; - drvr1_en = 0x34; + drvr0_en = 0x30; + drvr1_en = 0x30; } writel(drvr0_en, qmp->dp_tx + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); @@ -3584,6 +3659,14 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) writel(drvr1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); writel(bias1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]); + writel(0x03, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x23, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x22, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + + writel(0x0a, qmp->dp_tx + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + writel(0x0a, qmp->dp_tx2 + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + + writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); writel(0x08, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); udelay(100); writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); @@ -3591,16 +3674,24 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], status, - ((status & BIT(1)) > 0), + ((status & BIT(0)) > 0), 500, 10000)) return -ETIMEDOUT; - writel(0x00, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x00, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; - writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; return 0; } diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h index d8ac4c4a2c316..b35b486cfa566 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h @@ -71,5 +71,7 @@ #define QSERDES_V8_COM_ADDITIONAL_MISC 0x1b4 #define QSERDES_V8_COM_CMN_STATUS 0x2c8 #define QSERDES_V8_COM_C_READY_STATUS 0x2f0 +#define QSERDES_V8_COM_CMN_STATUS_N3 0x314 +#define QSERDES_V8_COM_C_READY_STATUS_N3 0x33c #endif From 04425138790a1da07aecc15e45d849fed449ec8e Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Mon, 4 May 2026 13:50:52 +0530 Subject: [PATCH 0441/1058] FROMLIST: drm/bridge: add support for lontium lt9211c bridge LT9211c is a Single/Dual-Link DSI/LVDS or Single DPI input to Single-link/Dual-Link DSI/LVDS or Single DPI output bridge chip. Extend the existing lontium-lt9211 driver to support DSI-to-LVDS bridge configuration. Signed-off-by: Yi Zhang Signed-off-by: Nilesh Laad Signed-off-by: Gopi Botlagunta Link:https://lore.kernel.org/all/20260323-add-lt9211c-bridge-v5-2-9c63bb035c17@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/lontium-lt9211.c | 842 ++++++++++++++++++++++-- 1 file changed, 802 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 870175a848390..2d14fa0b3a9a2 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -36,20 +37,39 @@ #define REG_CHIPID2 0x8102 #define REG_CHIPID2_VALUE 0xe3 +/* LT9211C chip ID values */ +#define REG_CHIPID0_LT9211C_VALUE 0x21 +#define REG_CHIPID1_LT9211C_VALUE 0x03 +#define REG_CHIPID2_LT9211C_VALUE 0xe1 + #define REG_DSI_LANE 0xd000 /* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */ #define REG_DSI_LANE_COUNT(n) ((n) & 3) +/* Chip type enum */ +enum lt9211_chip_type { + LT9211, + LT9211C, +}; + struct lt9211 { struct drm_bridge bridge; struct device *dev; struct regmap *regmap; - struct mipi_dsi_device *dsi; + struct mipi_dsi_device *dsi; struct drm_bridge *panel_bridge; struct gpio_desc *reset_gpio; struct regulator *vccio; - bool lvds_dual_link; - bool lvds_dual_link_even_odd_swap; + bool lvds_dual_link; + bool lvds_dual_link_even_odd_swap; + /* LT9211C specific fields */ + enum lt9211_chip_type chip_type; + struct workqueue_struct *wq; + struct delayed_work lt9211_dw; + struct drm_display_mode mode; + bool bpp24; + bool jeida; + bool de; }; static const struct regmap_range lt9211_rw_ranges[] = { @@ -93,6 +113,49 @@ static const struct regmap_config lt9211_regmap_config = { .max_register = 0xda00, }; +static const struct regmap_range lt9211c_rw_ranges[] = { + regmap_reg_range(0xff, 0xff), + regmap_reg_range(0x8100, 0x8182), + regmap_reg_range(0x8200, 0x82aa), + regmap_reg_range(0x8500, 0x85ff), + regmap_reg_range(0x8600, 0x86a0), + regmap_reg_range(0x8700, 0x8746), + regmap_reg_range(0xd000, 0xd0a7), + regmap_reg_range(0xd400, 0xd42c), + regmap_reg_range(0xd800, 0xd838), + regmap_reg_range(0xd9c0, 0xd9d5), +}; + +static const struct regmap_access_table lt9211c_rw_table = { + .yes_ranges = lt9211c_rw_ranges, + .n_yes_ranges = ARRAY_SIZE(lt9211c_rw_ranges), +}; + +static const struct regmap_range_cfg lt9211c_range = { + .name = "lt9211c", + .range_min = 0x0000, + .range_max = 0xda00, + .selector_reg = REG_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, +}; + +static const struct regmap_config lt9211c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .rd_table = <9211c_rw_table, + .wr_table = <9211c_rw_table, + .volatile_table = <9211c_rw_table, + .ranges = <9211c_range, + .num_ranges = 1, + .cache_type = REGCACHE_RBTREE, + .max_register = 0xda00, +}; + +static void lt9211_delayed_work_func(struct work_struct *work); + static struct lt9211 *bridge_to_lt9211(struct drm_bridge *bridge) { return container_of(bridge, struct lt9211, bridge); @@ -120,14 +183,21 @@ static int lt9211_read_chipid(struct lt9211 *ctx) return ret; } - /* Test for known Chip ID. */ - if (chipid[0] != REG_CHIPID0_VALUE || chipid[1] != REG_CHIPID1_VALUE) { - dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n", - chipid[0], chipid[1], chipid[2]); - return -EINVAL; + /* Test for LT9211 Chip ID. */ + if (chipid[0] == REG_CHIPID0_VALUE && chipid[1] == REG_CHIPID1_VALUE) { + dev_dbg(ctx->dev, "Detected LT9211 chip\n"); + return 0; } - return 0; + /* Test for LT9211C Chip ID. */ + if (chipid[0] == REG_CHIPID0_LT9211C_VALUE && chipid[1] == REG_CHIPID1_LT9211C_VALUE) { + dev_dbg(ctx->dev, "Detected LT9211C chip\n"); + return 0; + } + + dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + + return -EINVAL; } static int lt9211_system_init(struct lt9211 *ctx) @@ -504,8 +574,8 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, lvds_format_24bpp = true; lvds_format_jeida = false; dev_warn(ctx->dev, - "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", - bridge_state->output_bus_cfg.format); + "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", + bridge_state->output_bus_cfg.format); break; } @@ -518,35 +588,42 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; crtc_state = drm_atomic_get_new_crtc_state(state, crtc); mode = &crtc_state->adjusted_mode; - ret = lt9211_read_chipid(ctx); if (ret) return; - ret = lt9211_system_init(ctx); - if (ret) + if (ctx->chip_type == LT9211C && ctx->wq) { + drm_mode_copy(&ctx->mode, mode); + /* LT9211C must enable after mipi clock enable */ + queue_delayed_work(ctx->wq, &ctx->lt9211_dw, + msecs_to_jiffies(100)); + dev_dbg(ctx->dev, "LT9211C enabled.\n"); return; + } + ret = lt9211_system_init(ctx); + if (ret) + return; - ret = lt9211_configure_rx(ctx); - if (ret) - return; + ret = lt9211_configure_rx(ctx); + if (ret) + return; - ret = lt9211_autodetect_rx(ctx, mode); - if (ret) - return; + ret = lt9211_autodetect_rx(ctx, mode); + if (ret) + return; - ret = lt9211_configure_timing(ctx, mode); - if (ret) - return; + ret = lt9211_configure_timing(ctx, mode); + if (ret) + return; - ret = lt9211_configure_plls(ctx, mode); - if (ret) - return; + ret = lt9211_configure_plls(ctx, mode); + if (ret) + return; ret = lt9211_configure_tx(ctx, lvds_format_jeida, lvds_format_24bpp, - bus_flags & DRM_BUS_FLAG_DE_HIGH); - if (ret) - return; + bus_flags & DRM_BUS_FLAG_DE_HIGH); + if (ret) + return; dev_dbg(ctx->dev, "LT9211 enabled.\n"); } @@ -671,11 +748,6 @@ static int lt9211_parse_dt(struct lt9211 *ctx) static int lt9211_host_attach(struct lt9211 *ctx) { - const struct mipi_dsi_device_info info = { - .type = "lt9211", - .channel = 0, - .node = NULL, - }; struct device *dev = ctx->dev; struct device_node *host_node; struct device_node *endpoint; @@ -684,6 +756,8 @@ static int lt9211_host_attach(struct lt9211 *ctx) int dsi_lanes; int ret; + /* Check if the compatible string matches lt9211c */ + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4); host_node = of_graph_get_remote_port_parent(endpoint); @@ -697,7 +771,22 @@ static int lt9211_host_attach(struct lt9211 *ctx) if (dsi_lanes < 0) return dsi_lanes; - dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (ctx->chip_type == LT9211C) { + const struct mipi_dsi_device_info info = { + .type = "lt9211c", + .channel = 0, + .node = NULL, + }; + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + } else { + const struct mipi_dsi_device_info info = { + .type = "lt9211", + .channel = 0, + .node = NULL, + }; + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + } + if (IS_ERR(dsi)) return dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n"); @@ -706,10 +795,16 @@ static int lt9211_host_attach(struct lt9211 *ctx) dsi->lanes = dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | - MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | - MIPI_DSI_MODE_NO_EOT_PACKET; + + if (ctx->chip_type == LT9211C) { + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; + } else { + dsi->mode_flags = + MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | + MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | + MIPI_DSI_MODE_NO_EOT_PACKET; + } ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { @@ -731,6 +826,7 @@ static int lt9211_probe(struct i2c_client *client) return PTR_ERR(ctx); ctx->dev = dev; + ctx->chip_type = LT9211; /* * Put the chip in reset, pull nRST line low, @@ -744,13 +840,29 @@ static int lt9211_probe(struct i2c_client *client) usleep_range(10000, 11000); /* Very long reset duration. */ ret = lt9211_parse_dt(ctx); + if (ret) return ret; - ctx->regmap = devm_regmap_init_i2c(client, <9211_regmap_config); + if (of_device_is_compatible(dev->of_node, "lontium,lt9211c")) { + ctx->chip_type = LT9211C; + ctx->regmap = + devm_regmap_init_i2c(client, <9211c_regmap_config); + } else { + ctx->chip_type = LT9211; + ctx->regmap = + devm_regmap_init_i2c(client, <9211_regmap_config); + } if (IS_ERR(ctx->regmap)) return PTR_ERR(ctx->regmap); + /* Initialize LT9211C-specific fields */ + ctx->wq = create_workqueue("lt9211_work"); + if (!ctx->wq) + return -ENOMEM; + + INIT_DELAYED_WORK(&ctx->lt9211_dw, lt9211_delayed_work_func); + dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); @@ -768,17 +880,667 @@ static void lt9211_remove(struct i2c_client *client) { struct lt9211 *ctx = i2c_get_clientdata(client); + if (ctx->wq) + destroy_workqueue(ctx->wq); + drm_bridge_remove(&ctx->bridge); } +static int lt9211c_configure_rx(struct lt9211 *ctx) +{ + unsigned int pval; + + const struct reg_sequence lt9211c_rx_phy_seq[] = { + { REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) }, + { 0x8201, 0x11 }, + { 0x8218, 0x48 }, + { 0x8201, 0x91 }, + { 0x8202, 0x00 }, + { 0x8203, 0xee }, + { 0x8209, 0x21 }, + { 0x8204, 0x44 }, + { 0x8205, 0xc4 }, + { 0x8206, 0x44 }, + { 0x8213, 0x0c }, + + { 0xd001, 0x00 }, + { 0xd002, 0x0e }, + { 0xd005, 0x00 }, + { 0xd00a, 0x59 }, + { 0xd00b, 0x20 }, + }; + + const struct reg_sequence lt9211c_rx_phy_reset_seq[] = { + { 0x8109, 0xde }, + { 0x8109, 0xdf }, + }; + + const struct reg_sequence lt9211c_rx_clk_sel_seq[] = { + { 0x85e9, 0x88 }, + { 0x8180, 0x51 }, + { 0x8181, 0x10 }, + { 0x8632, 0x03 }, + }; + + const struct reg_sequence lt9211c_rx_input_sel_seq[] = { + { 0xd004, 0x00 }, + { 0xd021, 0x46 }, + }; + + const struct reg_sequence lt9211c_rx_dig_seq[] = { + { 0x853f, 0x08 }, + { 0x8540, 0x04 }, + { 0x8541, 0x03 }, + { 0x8542, 0x02 }, + { 0x8543, 0x01 }, + { 0x8545, 0x04 }, + { 0x8546, 0x03 }, + { 0x8547, 0x02 }, + { 0x8548, 0x01 }, + { 0x8544, 0x00 }, + { 0x8549, 0x00 }, + }; + + int ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_seq, + ARRAY_SIZE(lt9211c_rx_phy_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_reset_seq, + ARRAY_SIZE(lt9211c_rx_phy_reset_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_clk_sel_seq, + ARRAY_SIZE(lt9211c_rx_clk_sel_seq)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8180, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8180, ((pval & 0xfc) | 0x03)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8680, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, (pval & 0xf8)); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x05); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8530, ((pval & 0xf8) | 0x11)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_input_sel_seq, + ARRAY_SIZE(lt9211c_rx_input_sel_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_dig_seq, + ARRAY_SIZE(lt9211c_rx_dig_seq)); + if (ret) + return ret; + + /* Give the chip time to lock onto RX stream. */ + msleep(100); + + return 0; +} + +static int lt9211c_autodetect_rx(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + u16 width, height; + u8 buf[5]; + u8 format; + u8 sot[8]; + int ret; + + /* Read the SOT from the chip. */ + ret = regmap_bulk_read(ctx->regmap, 0xd088, sot, sizeof(sot)); + if (ret) + return ret; + + dev_dbg(ctx->dev, "Sot Num = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", sot[0], + sot[2], sot[4], sot[6]); + + dev_dbg(ctx->dev, "Sot Data = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", sot[1], + sot[3], sot[5], sot[7]); + /* HS Settle Set */ + if ((sot[0] > 0x10) && (sot[0] < 0x50)) + regmap_write(ctx->regmap, 0xd002, sot[0] - 5); + else + regmap_write(ctx->regmap, 0xd002, 0x08); + + /* Width/Height/Format Auto-detection */ + ret = regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf)); + if (ret) + return ret; + + width = (buf[0] << 8) | buf[1]; + height = (buf[3] << 8) | buf[4]; + format = buf[2] & 0xf; + + if (format == 0x3) { /* YUV422 16bit */ + width /= 2; + } else if (format == 0xa) { /* RGB888 24bit */ + width /= 3; + } else { + dev_err(ctx->dev, "Unsupported DSI format 0x%01x\n", format); + return -EINVAL; + } + + if (width != mode->hdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI width (%d) does not match mode hdisplay (%d)\n", + width, mode->hdisplay); + return -EINVAL; + } + + if (height != mode->vdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI height (%d) does not match mode vdisplay (%d)\n", + height, mode->vdisplay); + return -EINVAL; + } + + dev_dbg(ctx->dev, "RX: %dx%d format=0x%01x\n", width, height, format); + return 0; +} + +static int lt9211c_configure_timing(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_timing[] = { + { 0xd00d, (mode->vtotal >> 8) & 0xff }, + { 0xd00e, mode->vtotal & 0xff }, + { 0xd00f, (mode->vdisplay >> 8) & 0xff }, + { 0xd010, mode->vdisplay & 0xff }, + { 0xd011, (mode->htotal >> 8) & 0xff }, + { 0xd012, mode->htotal & 0xff }, + { 0xd013, (mode->hdisplay >> 8) & 0xff }, + { 0xd014, mode->hdisplay & 0xff }, + { 0xd015, (mode->vsync_end - mode->vsync_start) & 0xff }, + { 0xd04c, ((mode->hsync_end - mode->hsync_start) >> 8) & 0xff }, + { 0xd016, (mode->hsync_end - mode->hsync_start) & 0xff }, + { 0xd017, ((mode->vsync_start - mode->vdisplay) >> 8) & 0xff }, + { 0xd018, (mode->vsync_start - mode->vdisplay) & 0xff }, + { 0xd019, ((mode->hsync_start - mode->hdisplay) >> 8) & 0xff }, + { 0xd01a, (mode->hsync_start - mode->hdisplay) & 0xff }, + }; + + return regmap_multi_reg_write(ctx->regmap, lt9211c_timing, + ARRAY_SIZE(lt9211c_timing)); +} + +static int lt9211c_configure_plls(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_dessc_pll_reset[] = { + { 0x8103, 0xfe, 2000 }, + { 0x8103, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_pcr_cali_seq[] = { + { 0xd00a, 0x5f }, + { 0xd01e, 0x51 }, + { 0xd023, 0x80 }, + { 0xd024, 0x70 }, + { 0xd025, 0x80 }, + { 0xd02a, 0x10 }, + { 0xd021, 0x4f }, + { 0xd022, 0xf0 }, + { 0xd038, 0x04 }, + { 0xd039, 0x08 }, + { 0xd03a, 0x10 }, + { 0xd03b, 0x20 }, + { 0xd03f, 0x04 }, + { 0xd040, 0x08 }, + { 0xd041, 0x10 }, + { 0xd042, 0x20 }, + { 0xd02b, 0xA0 }, + }; + + const struct reg_sequence lt9211c_pcr_reset_seq[] = { + { 0xd009, 0xdb }, + { 0xd009, 0xdf }, + { 0xd008, 0x80 }, + { 0xd008, 0x00 }, + }; + + unsigned int pval; + int ret; + u8 div; + u32 pcr_m; + u32 pcr_k; + u32 pcr_up; + u32 pcr_down; + + /* DeSSC PLL reference clock is 25 MHz XTal. */ + ret = regmap_write(ctx->regmap, 0x8226, 0x20); + if (ret) + return ret; + + /* Prediv = 0 */ + ret = regmap_write(ctx->regmap, 0x8227, 0x40); + if (ret) + return ret; + + if (mode->clock < 22000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x07); + ret |= regmap_write(ctx->regmap, 0x822c, 0x01); + div = 16; + } else if (mode->clock < 44000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x07); + div = 16; + } else if (mode->clock < 88000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x06); + div = 8; + } else if (mode->clock < 176000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x05); + div = 4; + } else { + ret = regmap_write(ctx->regmap, 0x822f, 0x04); + div = 2; + } + + if (ret) + return ret; + + pcr_m = (mode->clock * div) / 25; + pcr_k = pcr_m % 1000; + pcr_m /= 1000; + + pcr_up = pcr_m + 1; + pcr_down = pcr_m - 1; + + pcr_k <<= 14; + + ret = regmap_write(ctx->regmap, 0xd008, 0x00); + if (ret < 0) + return ret; + + /* 0xd026: pcr_m */ + ret = regmap_write(ctx->regmap, 0xd026, (0x80 | (u8)pcr_m) & 0x7f); + if (ret < 0) + return ret; + + /* 0xd027 0xd028 0xd029: pcr_k */ + ret = regmap_write(ctx->regmap, 0xd027, (pcr_k >> 16) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd028, (pcr_k >> 8) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd029, pcr_k & 0xff); + if (ret < 0) + return ret; + + /* 0xd02d: pcr_m overflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd02d, pcr_up); + if (ret < 0) + return ret; + + /* 0xd031: pcr_m underflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd031, pcr_down); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_dessc_pll_reset, + ARRAY_SIZE(lt9211c_dessc_pll_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_cali_seq, + ARRAY_SIZE(lt9211c_pcr_cali_seq)); + if (ret) + return ret; + + if (mode->clock < 44000) { + ret = regmap_write(ctx->regmap, 0xd00c, 0x60); + ret |= regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |= regmap_write(ctx->regmap, 0xd01c, 0x60); + } else { + ret = regmap_write(ctx->regmap, 0xd00c, 0x40); + ret |= regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |= regmap_write(ctx->regmap, 0xd01c, 0x40); + } + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_reset_seq, + ARRAY_SIZE(lt9211c_pcr_reset_seq)); + if (ret) + return ret; + + /* PCR stability test takes seconds. */ + ret = regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, + ((pval & 0x18) == 0x18), 20000, 3000000); + if (ret) + dev_err(ctx->dev, "PCR unstable, ret=%i\n", ret); + + ret = regmap_write(ctx->regmap, 0x8180, 0x51); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x00); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x01); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8640, pval, + ((pval & 0x01) == 0x01), 50000, 250000); + if (ret) + dev_err(ctx->dev, "Video check not stable, ret=%i\n", ret); + + return ret; +} + +static int lt9211c_configure_tx(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_tx_phy_off_seq[] = { + { 0x8236, 0x00 }, + { 0x8237, 0x00 }, + { 0x8108, 0x6f }, + { 0x8103, 0xbf }, + }; + + const struct reg_sequence lt9211c_tx_phy_seq[] = { + { 0x8236, 0x03 }, + { 0x8237, 0x44 }, + { 0x8238, 0x14 }, + { 0x8239, 0x31 }, + { 0x823a, 0xc8 }, + { 0x823b, 0x00 }, + { 0x823c, 0x0f }, + { 0x8246, 0x40 }, + { 0x8247, 0x40 }, + { 0x8248, 0x40 }, + { 0x8249, 0x40 }, + { 0x824a, 0x40 }, + { 0x824b, 0x40 }, + { 0x824c, 0x40 }, + { 0x824d, 0x40 }, + { 0x824e, 0x40 }, + { 0x824f, 0x40 }, + { 0x8250, 0x40 }, + { 0x8251, 0x40 }, + }; + + const struct reg_sequence lt9211c_tx_mltx_reset[] = { + { 0x8103, 0xbf }, + { 0x8103, 0xff }, + }; + + const struct reg_sequence lt9211c_tx_dig_seq[] = { + { 0x854a, 0x01 }, + { 0x854b, 0x00 }, + { 0x854c, 0x10 }, + { 0x854d, 0x20 }, + { 0x854e, 0x50 }, + { 0x854f, 0x30 }, + { 0x8550, 0x46 }, + { 0x8551, 0x10 }, + { 0x8552, 0x20 }, + { 0x8553, 0x50 }, + { 0x8554, 0x30 }, + { 0x8555, 0x00 }, + { 0x8556, 0x20 }, + + { 0x8568, 0x00 }, + { 0x856e, 0x10 | (ctx->de ? BIT(6) : 0) }, + { 0x856f, 0x81 | (ctx->jeida ? BIT(6) : 0) | + (ctx->lvds_dual_link ? BIT(4) : 0) | + (ctx->bpp24 ? BIT(2) : 0) }, + }; + + const struct reg_sequence lt9211c_tx_ssc_seq[] = { + { 0x8234, 0x00 }, + { 0x856e, 0x10 }, + { 0x8181, 0x15 }, + { 0x871e, 0x00 }, + { 0x8717, 0x02 }, + { 0x8718, 0x04 }, + { 0x8719, 0xd4 }, + { 0x871A, 0x00 }, + { 0x871B, 0x12 }, + { 0x871C, 0x00 }, + { 0x871D, 0x24 }, + { 0x871F, 0x1c }, + { 0x8720, 0x00 }, + { 0x8721, 0x00 }, + { 0x871e, 0x02 }, + }; + + const struct reg_sequence lt9211c_tx_pll_reset_seq[] = { + { 0x810c, 0xfe, 2000 }, + { 0x810c, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_tx_sw_reset_seq[] = { + { 0x8108, 0x6f, 2000 }, + { 0x8108, 0x7f, 0 }, + }; + + unsigned int pval; + int ret; + u32 phy_clk; + u8 pixclk_div; + u8 pre_div; + u8 div_set; + u8 sericlk_div; + u8 val; + + dev_info(ctx->dev, + "dual_link=%d,even_odd_swap=%d,bpp24=%d,jeida=%d,de=%d\n", + ctx->lvds_dual_link, ctx->lvds_dual_link_even_odd_swap, + ctx->bpp24, ctx->jeida, ctx->de); + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_off_seq, + ARRAY_SIZE(lt9211c_tx_phy_off_seq)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8530, ((pval & 0x3f) | 0x40)); + if (ret) + return ret; + + /* [7]0:txpll normal work; txpll ref clk sel pix clk */ + ret = regmap_write(ctx->regmap, 0x8230, 0x00); + if (ret) + return ret; + + if (ctx->lvds_dual_link) + phy_clk = (u32)(mode->clock * 7 / 2); + else + phy_clk = (u32)(mode->clock * 7); + + /* 0x8231: prediv sel */ + if (mode->clock < 20000) { + val = 0x28; + pre_div = 1; + } else if (mode->clock < 40000) { + val = 0x28; + pre_div = 1; + } else if (mode->clock < 80000) { + val = 0x29; + pre_div = 2; + } else if (mode->clock < 160000) { + val = 0x2a; + pre_div = 4; + } else if (mode->clock < 320000) { + val = 0x2b; + pre_div = 8; + } else { + val = 0x2f; + pre_div = 16; + } + ret = regmap_write(ctx->regmap, 0x8231, val); + if (ret < 0) + return ret; + + /* 0x8232: serickdiv sel */ + if (phy_clk < 80000) { + val = 0x32; + sericlk_div = 16; + } else if (phy_clk < 160000) { + val = 0x22; + sericlk_div = 8; + } else if (phy_clk < 320000) { + val = 0x12; + sericlk_div = 4; + } else if (phy_clk < 640000) { + val = 0x02; + sericlk_div = 2; + } else { + val = 0x42; + sericlk_div = 1; + } + ret = regmap_write(ctx->regmap, 0x8232, val); + if (ret < 0) + return ret; + + /* 0x8233: pix_mux sel & pix_div sel + * To avoid floating point operations, The pixclk_div is enlarged by 10 times + */ + if (mode->clock > 150000) { + val = 0x04; + pixclk_div = 35; + } else { + pixclk_div = + (u8)((phy_clk * sericlk_div * 10) / (mode->clock * 7)); + if (pixclk_div <= 10) + val = 0x00; + else if (pixclk_div <= 20) + val = 0x01; + else if (pixclk_div <= 40) + val = 0x02; + else + val = 0x03; + } + ret = regmap_write(ctx->regmap, 0x8233, val); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0x8234, 0x01); + if (ret < 0) + return ret; + + /* 0x8235: div set */ + div_set = (u8)(phy_clk * sericlk_div / mode->clock / pre_div); + ret = regmap_write(ctx->regmap, 0x8235, div_set); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_ssc_seq, + ARRAY_SIZE(lt9211c_tx_ssc_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_pll_reset_seq, + ARRAY_SIZE(lt9211c_tx_pll_reset_seq)); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8739, pval, pval & 0x04, + 10000, 1000000); + if (ret) { + dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_seq, + ARRAY_SIZE(lt9211c_tx_phy_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_mltx_reset, + ARRAY_SIZE(lt9211c_tx_mltx_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_dig_seq, + ARRAY_SIZE(lt9211c_tx_dig_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_sw_reset_seq, + ARRAY_SIZE(lt9211c_tx_sw_reset_seq)); + if (ret) + return ret; + + return 0; +} + +static void lt9211_delayed_work_func(struct work_struct *work) +{ + struct delayed_work *dw = to_delayed_work(work); + struct lt9211 *ctx = container_of(dw, struct lt9211, lt9211_dw); + int ret; + const struct drm_display_mode *mode = &ctx->mode; + + /* For LT9211C */ + if (ctx->chip_type != LT9211C) { + dev_err(ctx->dev, "LT9211: Delayed work called for non-LT9211C chip\n"); + return; + } + ret = lt9211c_configure_rx(ctx); + if (ret) + return; + + ret = lt9211c_autodetect_rx(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_timing(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_plls(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_tx(ctx, mode); + if (ret) + return; + +} + static const struct i2c_device_id lt9211_id[] = { { "lontium,lt9211" }, + { "lontium,lt9211c" }, {}, }; MODULE_DEVICE_TABLE(i2c, lt9211_id); static const struct of_device_id lt9211_match_table[] = { { .compatible = "lontium,lt9211" }, + { .compatible = "lontium,lt9211c" }, {}, }; MODULE_DEVICE_TABLE(of, lt9211_match_table); From 59b742e1909e50b4e2a1737e39beb1420477b736 Mon Sep 17 00:00:00 2001 From: Gopi Botlagunta Date: Fri, 21 Nov 2025 19:12:06 +0530 Subject: [PATCH 0442/1058] FROMLIST: drm/bridge: lt9611uxc: Increase EDID wait time from 500ms to 1000ms EDID interrupt was coming 600-650 ms after HPD interrupt, resulting into EDID read timeout and default resolution of 1024x768 on display. Signed-off-by: Gopi Botlagunta Link: https://lore.kernel.org/all/20251121-hdmibridge-v1-1-14c63890f362@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 2e59318ccf2ba..0bb07916a0487 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -383,7 +383,7 @@ lt9611uxc_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connect static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc) { return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read, - msecs_to_jiffies(500)); + msecs_to_jiffies(1000)); } static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) From 46b373eb57afb10222dbcd54ec457bea3b1e531c Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 26 Nov 2025 17:01:18 +0530 Subject: [PATCH 0443/1058] FROMLIST: drm/bridge: lt9611uxc: extend mode valid checks Currently valid mode checks are only for hdisplay and vdisplay, add htotal and vtotal to filter only specific modes. Link:https://lore.kernel.org/lkml/20251126-lt9611uxc-modes-v2-1-34bf9b351921@oss.qualcomm.com/ Signed-off-by: Nilesh Laad Signed-off-by: Mahadevan P --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 0bb07916a0487..ed311b4b4e04f 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -87,7 +87,9 @@ static const struct regmap_config lt9611uxc_regmap_config = { struct lt9611uxc_mode { u16 hdisplay; + u16 htotal; u16 vdisplay; + u16 vtotal; u8 vrefresh; }; @@ -96,22 +98,22 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { - { 1920, 1080, 60 }, - { 1920, 1080, 30 }, - { 1920, 1080, 25 }, - { 1366, 768, 60 }, - { 1360, 768, 60 }, - { 1280, 1024, 60 }, - { 1280, 800, 60 }, - { 1280, 720, 60 }, - { 1280, 720, 50 }, - { 1280, 720, 30 }, - { 1152, 864, 60 }, - { 1024, 768, 60 }, - { 800, 600, 60 }, - { 720, 576, 50 }, - { 720, 480, 60 }, - { 640, 480, 60 }, + { 1920, 2200, 1080, 1125, 60 }, + { 1920, 2200, 1080, 1125, 30 }, + { 1920, 2640, 1080, 1125, 25 }, + { 1366, 1792, 768, 798, 60 }, + { 1360, 1792, 768, 795, 60 }, + { 1280, 1688, 1024, 1066, 60 }, + { 1280, 1680, 800, 831, 60 }, + { 1280, 1650, 720, 750, 60 }, + { 1280, 1980, 720, 750, 50 }, + { 1280, 3300, 720, 750, 30 }, + { 1152, 1600, 864, 900, 60 }, + { 1024, 1344, 768, 806, 60 }, + { 800, 1056, 600, 628, 60 }, + { 720, 864, 576, 625, 50 }, + { 720, 858, 480, 525, 60 }, + { 640, 800, 480, 525, 60 }, }; static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) @@ -238,7 +240,9 @@ static struct lt9611uxc_mode *lt9611uxc_find_mode(const struct drm_display_mode for (i = 0; i < ARRAY_SIZE(lt9611uxc_modes); i++) { if (lt9611uxc_modes[i].hdisplay == mode->hdisplay && + lt9611uxc_modes[i].htotal == mode->htotal && lt9611uxc_modes[i].vdisplay == mode->vdisplay && + lt9611uxc_modes[i].vtotal == mode->vtotal && lt9611uxc_modes[i].vrefresh == drm_mode_vrefresh(mode)) { return <9611uxc_modes[i]; } From 4c6e7edf901e8c57ffa0750a6c5facb3554bf1c8 Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 26 Nov 2025 18:52:37 +0530 Subject: [PATCH 0444/1058] FROMLIST: drm/bridge: lt9611uxc: add support for 4K@30 resolution Add 3840x2160@30 mode in lt9611uxc modes to add support for 4K@30 resolution. Link:https://lore.kernel.org/r/20251126-lt9611uxc-4k30-v2-1-3de0ea58c24e@oss.qualcomm.com Signed-off-by: Nilesh Laad Signed-off-by: Mahadevan P --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index ed311b4b4e04f..b6bf2fe7cb2ce 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -98,6 +98,7 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { + { 3840, 4400, 2160, 2250, 30 }, { 1920, 2200, 1080, 1125, 60 }, { 1920, 2200, 1080, 1125, 30 }, { 1920, 2640, 1080, 1125, 25 }, From 0a52ffb7c446bc2cfd3d15898bf22a88201d4bfc Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:52:59 +0530 Subject: [PATCH 0445/1058] FROMLIST: arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP/Modem does not throttle its speed automatically when it reaches high temperatures in kodiak. Set up CDSP cooling by throttling the cdsp when it reaches 100°C and for modem when it reaches to 95°C. Remove inherited mdmss cooling-map nodes for Non Modem kodiak variant. Signed-off-by: Gaurav Kohli Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-4-291a2ff4c634@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 127 +++++++++++++++++- .../dts/qcom/qcs6490-radxa-dragon-q6a.dts | 17 +++ .../qcom/qcs6490-thundercomm-minipc-g1iot.dts | 17 +++ .../dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 17 +++ .../dts/qcom/sc7280-herobrine-lte-sku.dtsi | 18 +++ .../dts/qcom/sc7280-herobrine-wifi-sku.dtsi | 16 +++ 6 files changed, 208 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 28b09b5ff4a65..2cf6973401234 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3427,6 +3427,9 @@ qcom,smem-states = <&modem_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + tmd-names = "pa", "modem"; + status = "disabled"; glink-edge { @@ -4787,6 +4790,9 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -4906,6 +4912,7 @@ }; }; }; + }; usb_1: usb@a600000 { @@ -7716,6 +7723,8 @@ }; nspss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 3>; trips { @@ -7725,15 +7734,31 @@ type = "hot"; }; + nspss0_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss0_crit: nspss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss0_alert1>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nspss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 4>; trips { @@ -7743,12 +7768,26 @@ type = "hot"; }; + nspss1_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss1_crit: nspss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss1_alert1>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; video-thermal { @@ -7787,7 +7826,9 @@ }; }; - mdmss0-thermal { + mdmss0_thermal: mdmss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 7>; trips { @@ -7797,15 +7838,35 @@ type = "hot"; }; + mdmss0_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss0_crit: mdmss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss1-thermal { + mdmss1_thermal: mdmss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 8>; trips { @@ -7815,15 +7876,35 @@ type = "hot"; }; + mdmss1_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss1_crit: mdmss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss2-thermal { + mdmss2_thermal: mdmss2-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 9>; trips { @@ -7833,15 +7914,35 @@ type = "hot"; }; + mdmss2_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss2_crit: mdmss2-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss3-thermal { + mdmss3_thermal: mdmss3-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 10>; trips { @@ -7851,12 +7952,30 @@ type = "hot"; }; + mdmss3_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss3_crit: mdmss3-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; camera0-thermal { diff --git a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts index bb5a42b038f19..400d128132fcb 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts @@ -24,6 +24,23 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts index a5ad796cb65d0..1e190ed18ae5a 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts @@ -22,6 +22,23 @@ /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; /delete-node/ &mpss_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; /delete-node/ &rmtfs_mem; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index f47efca42d48d..8e8dd4efd8c09 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -23,6 +23,23 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi index b721a8546800c..e2c0a317ecb81 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi @@ -26,8 +26,26 @@ status = "okay"; }; +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + &remoteproc_mpss { compatible = "qcom,sc7280-mss-pil"; + /delete-property/ tmd-names; + /delete-property/ #cooling-cells; reg = <0 0x04080000 0 0x10000>, <0 0x04180000 0 0x48>; reg-names = "qdsp6", "rmb"; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi index 3ebc915f0dc2f..6642076f62c49 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi @@ -7,6 +7,22 @@ /* WIFI SKUs save 256M by not having modem/mba/rmtfs memory regions defined. */ +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &rmtfs_mem; From 002e0be0ee86ea080be0c16eff60634130d4c3c6 Mon Sep 17 00:00:00 2001 From: Gopi Botlagunta Date: Fri, 30 Jan 2026 15:57:25 +0530 Subject: [PATCH 0446/1058] FROMLIST: arm64: dts: qcom: Enable lvds panel-DV215FHM-R01 for rb3gen2 industrial mezzanine Below is the routing diagram of dsi lanes from qcs6490 soc to mezzanine. DSI0 --> SW1403.4 --> LT9611uxc --> hdmi port | --> SW2700.1 --> dsi connector | --> LT9211c --> LVDS connector Disable hdmi connector for industrial mezzanine and enable LT9211c bridge and lvds panel node. LT9211c is powered by default with reset gpio connected to 117. Link: https://lore.kernel.org/r/20260130-add-lt9211c-bridge-for-rb3gen2-industrial-mezzanine-v2-1-a98714fa1531@oss.qualcomm.com Signed-off-by: Gopi Botlagunta Co-developed-by: Yi Zhang Signed-off-by: Yi Zhang --- .../qcs6490-rb3gen2-industrial-mezzanine.dtso | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index 83908db335afa..55e6a049180ca 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -34,6 +34,112 @@ &remoteproc_wpss { status = "disabled"; + +}; +/ { + + hdmi-connector { + status = "disabled"; + }; + + panel_lvds: panel-lvds@0 { + compatible = "panel-lvds"; + data-mapping = "vesa-24"; + width-mm = <476>; + height-mm = <268>; + + status = "okay"; + + panel-timing { + clock-frequency = <148500000>; + hactive = <1920>; + vactive = <1080>; + hfront-porch = <88>; + hback-porch = <148>; + hsync-len = <44>; + vfront-porch = <4>; + vback-porch = <36>; + vsync-len = <5>; + de-active = <1>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dual-lvds-odd-pixels; + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + + dual-lvds-even-pixels; + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + + }; + }; + }; + +}; + +&i2c1 { + status = "okay"; + + lvds_bridge: lvds-bridge@29 { + compatible = "lontium,lt9211c"; + reg = <0x29>; + reset-gpios = <&tlmm 117 1>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; + + +}; + +<9611_codec { + status = "disabled"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9211c_in>; }; &spi11 { From e2beb93a3b9afeef7e01050d991461d81d701d6e Mon Sep 17 00:00:00 2001 From: Janaki Ramaiah Thota Date: Tue, 3 Feb 2026 12:48:07 +0530 Subject: [PATCH 0447/1058] FROMLIST: arm64: dts: qcom: qcm6490-idp: add and enable BT node Add the PMU node for WCN6750 present on the qcm6490-idp board and assign its power outputs to the Bluetooth module. In WCN6750 module sw_ctrl and wifi-enable pins are handled in the wifi controller firmware. Therefore, it is not required to have those pins' entries in the PMU node. Link: https://lore.kernel.org/r/20260203071807.764036-1-janaki.thota@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Janaki Ramaiah Thota --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 76a7d3fef1a91..3d606d8ab2292 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -793,6 +793,39 @@ }; }; +&qup_uart7_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart7_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart7_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart7_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + &qupv3_id_0 { status = "okay"; }; From 98f83e3f4dcb65f5af62e95f19191def0d277661 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Thu, 12 Feb 2026 17:36:29 +0530 Subject: [PATCH 0448/1058] FROMLIST: arm64: dts: qcom: qcm6490-idp: Enable PCIe1 Remove PCIe1 clocks from protected-list and enable PCIe1 controller and its corresponding PHY nodes on qcm6490-idp platform. PCIe1 is used to connect NVMe based SSD's on this platform. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260212-qcm6490-idp-v1-1-80a45bd46ac5@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 39 ++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 3d606d8ab2292..53c9689ae63c1 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -591,12 +591,7 @@ }; &gcc { - protected-clocks = ,, - , , - , , - , , - , , - , , + protected-clocks = , , ,, , , , @@ -673,6 +668,22 @@ status = "okay"; }; +&pcie1 { + perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie1_reset_n>, <&pcie1_wake_n>, <&pcie1_clkreq_n>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l10c_0p88>; + vdda-pll-supply = <&vreg_l6b_1p2>; + + status = "okay"; +}; + &pm7250b_gpios { lcd_disp_bias_en: lcd-disp-bias-en-state { pins = "gpio2"; @@ -1104,6 +1115,22 @@ bias-pull-up; }; + pcie1_reset_n: pcie1-reset-n-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <16>; + output-low; + bias-disable; + }; + + pcie1_wake_n: pcie1-wake-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + sd_cd: sd-cd-state { pins = "gpio91"; function = "gpio"; From 054aa85a53ddc7d77dd45c484d0b46e3ba89c856 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Sat, 28 Feb 2026 12:29:05 +0530 Subject: [PATCH 0449/1058] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: use DP controller native HPD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The base device tree configures the edp_hot_plug_det pin using the "edp_hot" function on GPIO 60. However, on qcs6490-rb3gen2 this external HPD GPIO does not generate a connect event when a display is already connected at boot, causing the DP/eDP display to remain disabled. The DP controller’s native HPD correctly detects the connected sink in this scenario, so continue using the DP controller native HPD on the qcs6490-rb3gen2 platform instead of the external HPD GPIO. Link: https://lore.kernel.org/all/20260228-edp_hpd_rb3_gen2_for_next-v1-1-aebc047eddc1@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index decc964d2d98b..cd4335b2fbb87 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -57,8 +57,6 @@ label = "DP"; type = "mini"; - hpd-gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; - port { dp_connector_in: endpoint { remote-endpoint = <&mdss_edp_out>; @@ -1479,7 +1477,6 @@ /* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */ &edp_hot_plug_det { - function = "gpio"; bias-disable; }; From 04b0ed671f6012020ee58ca0dca1ba19248bfc6b Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Thu, 8 Jan 2026 18:21:59 +0530 Subject: [PATCH 0450/1058] FROMLIST: dt-bindings: can: microchip,mcp251xfd: allow gpio-hog child nodes The MCP251XFD can expose two pins as GPIOs. The binding already declares gpio-controller and #gpio-cells for the device. Whitelist GPIO hog child nodes using patternProperties so boards can set default GPIO states at boot via DT, consistent with other GPIO controllers (e.g. microchip,mpfs-gpio). Signed-off-by: Viken Dadhaniya Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/all/20260108125200.2803112-2-viken.dadhaniya@oss.qualcomm.com/ --- .../devicetree/bindings/net/can/microchip,mcp251xfd.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml index 28e494262cd92..3a4bcb3e56583 100644 --- a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml +++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml @@ -62,6 +62,12 @@ properties: "#gpio-cells": const: 2 +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + required: + - gpio-hog + required: - compatible - reg From d160df137135234471a9a88b66715b03bdd673ca Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 6 Feb 2026 02:44:08 +0530 Subject: [PATCH 0451/1058] FROMLIST: arm64: dts: qcom: pm8350c: Enable Qualcomm BCL device Enable Qualcomm BCL hardware devicetree binding configuration for pm8350c. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260206-qcom-bcl-hwmon-v1-4-7b426f0b77a1@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pm8350c.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi index 1a24e6439e36d..f0cf55a7fc9e5 100644 --- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi @@ -41,6 +41,15 @@ #pwm-cells = <2>; status = "disabled"; }; + + sensor@4700 { + compatible = "qcom,pm8350c-bcl", "qcom,bcl-v2"; + reg = <0x4700>; + interrupts = <0x2 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x47 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "bcl-max-min", + "bcl-critical"; + }; }; }; From ba90377259348a74de8d9d3e639dcd34255f30b9 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 6 Feb 2026 02:44:07 +0530 Subject: [PATCH 0452/1058] FROMLIST: arm64: dts: qcom: pm7250b: Enable Qualcomm BCL device Enable Qualcomm BCL hardware devicetree binding configuration for pm7250b. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260206-qcom-bcl-hwmon-v1-3-7b426f0b77a1@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pm7250b.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi index 43cab07126c5c..363a1d6769c63 100644 --- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi @@ -201,6 +201,16 @@ interrupt-controller; #interrupt-cells = <2>; }; + + sensor@1d00 { + compatible = "qcom,pm7250b-bcl", "qcom,bcl-v1"; + reg = <0x1d00>; + interrupts = , + ; + interrupt-names = "bcl-max-min", + "bcl-critical"; + overcurrent-thresholds-milliamp = <5500 6000>; + }; }; pmic@PM7250B_SID1 { From 751c7cb7ba369559d36eccda002d514b8d0c596b Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 20 Apr 2026 15:30:02 +0530 Subject: [PATCH 0453/1058] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Enable 4-lane DisplayPort Alt Mode Add the mode-switch property to the QMP combo PHY so that mode-switch events are routed to it, allowing the PHY to enter DisplayPort Alternate Mode. Expand the DP data-lanes assignment from two to four lanes to make use of the full link bandwidth available in this configuration. Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20260420-kodiak_4k-v1-1-83dfc66b8f06@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index cd4335b2fbb87..7416b382ae421 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -804,7 +804,7 @@ }; &mdss_dp_out { - data-lanes = <0 1>; + data-lanes = <0 1 2 3>; remote-endpoint = <&usb_dp_qmpphy_dp_in>; }; @@ -1427,6 +1427,7 @@ vdda-phy-supply = <&vreg_l6b_1p2>; vdda-pll-supply = <&vreg_l1b_0p912>; + mode-switch; orientation-switch; status = "okay"; From 52a4910c7ab457cc16bd814293e855af5c94b96e Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Wed, 22 Apr 2026 17:36:55 +0800 Subject: [PATCH 0454/1058] WORKAROUND: arm64: dts: qcom: sc7280: avoid EFI overlap for ADSP remote heap On KODIAK platforms boot can fail when the DT "adsp-rpc-remote-heap" reserved-memory region overlaps with firmware allocations (UEFI/EFI runtime). The kernel then reports failure to reserve the region and subsequent EFI runtime activity may trigger aborts. The remote heap node was described as a fixed "no-map" region, which turns it into a hard carveout. Replace it with a "shared-dma-pool" reserved memory region with reusable CMA-backed allocation, specifying alignment and size. This avoids hard carveouts and reduces the chance of conflicting with firmware memory maps while keeping an explicit pool for ADSP remote heap usage. Signed-off-by: Jianping Li --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 2cf6973401234..ac4964737a8ea 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -191,9 +191,12 @@ qcom,vmid = ; }; - adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap@9cb80000 { - reg = <0x0 0x9cb80000 0x0 0x800000>; - no-map; + adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; + reusable; + alignment = <0x0 0x400000>; + size = <0x0 0x800000>; }; }; From ddd39b202df9c792a654cd7ab4249c995b41ee18 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 13:04:46 +0530 Subject: [PATCH 0455/1058] FROMLIST: arm64: dts: qcom: Enable secondary mi2s Enable secondary mi2s to support HDMI audio. Link: https://lore.kernel.org/all/20260413091937.134469-2-kumar.singh@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 5 +++ arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 43 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index ac4964737a8ea..992045b7ea704 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -5958,6 +5958,11 @@ function = "mi2s1_ws"; }; + mi2s1_mclk: mi2s1-mclk-state { + pins = "gpio105"; + function = "sec_mi2s"; + }; + pcie0_clkreq_n: pcie0-clkreq-n-state { pins = "gpio88"; function = "pcie0_clkreqn"; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 7416b382ae421..b46e0778332e1 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -709,6 +709,7 @@ lt9611_codec: hdmi-bridge@2b { compatible = "lontium,lt9611uxc"; reg = <0x2b>; + #sound-dai-cells = <1>; interrupts-extended = <&tlmm 24 IRQ_TYPE_EDGE_FALLING>; reset-gpios = <&pm7250b_gpios 2 GPIO_ACTIVE_HIGH>; @@ -1189,6 +1190,9 @@ compatible = "qcom,qcs6490-rb3gen2-sndcard"; model = "QCS6490-RB3Gen2"; + pinctrl-0 = <&mi2s1_data0>, <&mi2s1_mclk>, <&mi2s1_sclk>, <&mi2s1_ws>; + pinctrl-names = "default"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", "SpkrRight IN", "WSA_SPK2 OUT", "VA DMIC0", "vdd-micb", @@ -1228,6 +1232,22 @@ sound-dai = <&q6apm>; }; }; + + mi2s1-playback-dai-link { + link-name = "Secondary MI2S Playback"; + + codec { + sound-dai = <<9611_codec 0>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; &spi3 { @@ -1566,3 +1586,26 @@ compatible = "qcom,qcm6490-lpassaudiocc"; /delete-property/ power-domains; }; + +&mi2s1_data0 { + drive-strength = <8>; + bias-disable; +}; + +&mi2s1_mclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_sclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_ws { + drive-strength = <8>; + bias-disable; + output-high; +}; From d56c76a77657361edf5ddcedc06b321c361f82b8 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 13:05:53 +0530 Subject: [PATCH 0456/1058] FROMLIST: arm64: dts: qcom: qcs6490: Enable DP audio Add new dai link to enable DP audio. Link: https://lore.kernel.org/all/20260413091937.134469-3-kumar.singh@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index b46e0778332e1..b5e511e49b4e9 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -1248,6 +1248,22 @@ sound-dai = <&q6apm>; }; }; + + dp-dai-link { + link-name = "DisplayPort0 Playback"; + + codec { + sound-dai = <&mdss_dp>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; &spi3 { From 4697e0a5a8900591343cb3d1f6028dc49d1cb8c2 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 12:35:59 +0530 Subject: [PATCH 0457/1058] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add WCD headset playback and record for qcs6490-rb3gen2 industrial mezzanine Add WCD playback and capture DAI link to sound node. Add WCD codec node and corresponding soundwire nodes to perform headset playback and record. Link: https://lore.kernel.org/all/20260423071951.3181130-1-karthik.s@oss.qualcomm.com/#t Signed-off-by: Karthik S --- .../qcs6490-rb3gen2-industrial-mezzanine.dtso | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index 55e6a049180ca..670566f99621c 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -6,6 +6,7 @@ /dts-v1/; /plugin/; #include +#include #include #include @@ -37,6 +38,29 @@ }; / { + wcd9370: audio-codec { + compatible = "qcom,wcd9370-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; + vdd-buck-supply = <&vph_pwr>; + vdd-rxtx-supply = <&vph_pwr>; + vdd-px-supply = <&vph_pwr>; + vdd-mic-bias-supply = <&vph_pwr>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,hphl-jack-type-normally-closed = <1>; + qcom,ground-jack-type-normally-closed = <1>; + qcom,rx-device = <&wcd937x_rx>; + qcom,tx-device = <&wcd937x_tx>; + + #sound-dai-cells = <1>; + }; + hdmi-connector { status = "disabled"; @@ -138,6 +162,14 @@ status = "disabled"; }; +&lpass_rx_macro { + status = "okay"; +}; + +&lpass_tx_macro { + status = "okay"; +}; + &mdss_dsi0_out { remote-endpoint = <<9211c_in>; }; @@ -350,6 +382,101 @@ }; }; +&sound { + model = "qcs6490-rb3gen2-ia-snd-card"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "TX SWR_ADC1", "ADC2_OUTPUT", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + codec { + sound-dai = <&wcd9370 1>, <&swr1 0>, <&lpass_tx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + codec { + sound-dai = <&wcd9370 0>, <&swr0 0>, <&lpass_rx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; +}; + +&swr0 { + status = "okay"; + + wcd937x_rx: codec@0,4 { + compatible = "sdw20217010a00"; + reg = <0 4>; + + /* + * WCD9370 RX Port 1 (HPH_L/R) <==> SWR1 Port 1 (HPH_L/R) + * WCD9370 RX Port 2 (CLSH) <==> SWR1 Port 2 (CLSH) + * WCD9370 RX Port 3 (COMP_L/R) <==> SWR1 Port 3 (COMP_L/R) + * WCD9370 RX Port 4 (LO) <==> SWR1 Port 4 (LO) + * WCD9370 RX Port 5 (DSD_L/R) <==> SWR1 Port 5 (DSD) + */ + qcom,rx-port-mapping = <1 2 3 4 5>; + + /* + * Static channels mapping between slave and master rx port channels. + * In the order of slave port channels, which is + * hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l. + */ + qcom,rx-channel-mapping = /bits/ 8 <1 2 1 1 2 1 1 2>; + }; +}; + +&swr1 { + status = "okay"; + wcd937x_tx: codec@0,3 { + compatible = "sdw20217010a00"; + reg = <0 3>; + + /* + * WCD9370 TX Port 1 (ADC1) <=> SWR2 Port 2 + * WCD9370 TX Port 2 (ADC2, 3) <=> SWR2 Port 2 + * WCD9370 TX Port 3 (DMIC0,1,2,3 & MBHC) <=> SWR2 Port 3 + * WCD9370 TX Port 4 (DMIC4,5,6,7) <=> SWR2 Port 4 + */ + qcom,tx-port-mapping = <1 1 2 3>; + + /* + * Static channel mapping between slave and master tx port channels. + * In the order of slave port channels which is adc1, adc2, adc3, + * mic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7. + */ + qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>; + }; +}; + + &tlmm { pcie0_tc9563_resx_n: pcie0-tc9563-resx-state { pins = "gpio78"; @@ -389,6 +516,12 @@ output-enable; }; + wcd_default: wcd-reset-n-active-state { + pins = "gpio83"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; }; &wifi { From a03943aa175d95f79ddd87ee5a7949e45d9ea4d1 Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Wed, 1 Apr 2026 16:14:37 +0800 Subject: [PATCH 0458/1058] FROMLIST: arm64: dts: qcom: kodiak: increase fastrpc compute-cb session slots Some workloads on Kodiak can exhaust FastRPC sessions when multiple compute clients open contexts concurrently, leading to -EBUSY failures. Describe the compute context bank with qcom,nsessions = <5> so the driver can provision enough session slots for the compute-cb instance. Link: https://lore.kernel.org/all/20260401073345.478-1-jianping.li@oss.qualcomm.com/ Signed-off-by: Jianping Li --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 992045b7ea704..7b815a6d48ef8 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4584,6 +4584,7 @@ compatible = "qcom,fastrpc-compute-cb"; reg = <5>; iommus = <&apps_smmu 0x1805 0x0>; + qcom,nsessions = <5>; dma-coherent; }; }; From 28d99b98af3aba1983f753094b7dc2a23d0d8729 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:17 +0530 Subject: [PATCH 0459/1058] FROMLIST: arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU On Kodiak platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-3-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 7b815a6d48ef8..12af85e2af0a7 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3389,6 +3389,8 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; gfx_0_tbu: tbu@3dd9000 { From 943de1305049f0583ecc1a1ed05c9bbb3b8e2c24 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 19:36:02 +0800 Subject: [PATCH 0460/1058] FROMLIST: arm64: dts: qcom: kodiak: Add label properties to CoreSight devices Add label properties to TPDM and CTI nodes in the kodiak device tree to provide human-readable identifiers for each CoreSight device. These labels allow userspace tools and the CoreSight framework to identify devices by name rather than by base address. Link: https://lore.kernel.org/linux-arm-msm/20260414-add-label-to-coresight-device-v2-4-5017d07358f2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 12af85e2af0a7..2842cb5d1ae9f 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3525,6 +3525,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3544,6 +3545,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss"; }; funnel@6041000 { @@ -3693,6 +3695,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao"; }; cti@6b01000 { @@ -3701,6 +3704,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_1"; }; cti@6b02000 { @@ -3709,6 +3713,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_2"; }; cti@6b03000 { @@ -3717,6 +3722,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_3"; }; funnel@6b04000 { @@ -3871,6 +3877,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3890,6 +3897,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3909,6 +3917,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3928,6 +3937,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3947,6 +3957,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3966,6 +3977,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; etm@7040000 { From 7b7fe03ea39cce59ff63a41d3bdf7b839186eb52 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 24 Jun 2026 12:09:52 +0530 Subject: [PATCH 0461/1058] FROMLIST: arm64: dts: qcom: kodiak: Add EL2 overlay All the existing variants Kodiak boards are using Gunyah hypervisor which means that, so far, Linux-based OS could only boot in EL1 on those devices. However, it is possible for us to boot Linux at EL2 on these devices [1]. When running under Gunyah, the remote processor firmware IOMMU streams are controlled by Gunyah. However, without Gunyah, the IOMMU is managed by the consumer of this DeviceTree. Therefore, describe the firmware streams for each remote processor. Add a EL2-specific DT overlay and apply it to Kodiak IOT variant devices to create -el2.dtb for each of them alongside "normal" dtb. Note that modem and media subsystems haven't been supported yet due to missing dependencies. For GPU to work, zap shader is disabled and in EL2 mode the kernel owns hardware watchdog which is enabled here. And for wifi to work wpss copy engine memory need to be mapped for WPSS firmware to work which is aligning with sc7280 chrome. [1] https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-4/boot-developer-touchpoints.html#uefi Link: https://lore.kernel.org/all/20260624063952.2242702-1-mukesh.ojha@oss.qualcomm.com/ Co-developed-by: Sumit Garg Signed-off-by: Sumit Garg Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/Makefile | 12 ++++++ arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 52 ++++++++++++++++++++++++ arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..d2cee1190954f 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -164,7 +164,11 @@ purwa-iot-evk-el2-dtbs := purwa-iot-evk.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-iot-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-fairphone-fp5.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp.dtb +qcm6490-idp-el2-dtbs := qcm6490-idp.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-particle-tachyon.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-shift-otter.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb @@ -176,12 +180,20 @@ qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb +qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-el2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +qcs6490-rb3gen2-industrial-mezzanine-el2-dtbs := qcs6490-rb3gen2-industrial-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +qcs6490-rb3gen2-vision-mezzanine-el2-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso new file mode 100644 index 0000000000000..91e4cda45b491 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak specific modifications required to boot in EL2. + */ + +/dts-v1/; +/plugin/; + +&gpu_zap_shader { + status = "disabled"; +}; + +&remoteproc_adsp { + iommus = <&apps_smmu 0x1800 0x0>; +}; + +&remoteproc_cdsp { + iommus = <&apps_smmu 0x11a0 0x0400>; +}; + +&remoteproc_mpss { + status = "disabled"; +}; + +&reserved_memory { + #address-cells = <2>; + #size-cells = <2>; + + wlan_ce_mem: wlan-ce@4cd000 { + no-map; + reg = <0x0 0x004cd000 0x0 0x1000>; + }; +}; + +&venus { + status = "disabled"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + memory-region = <&wlan_fw_mem>, <&wlan_ce_mem>; + status = "okay"; + + wifi-firmware { + iommus = <&apps_smmu 0x1c02 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 2842cb5d1ae9f..44a478afa2a5e 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -91,7 +91,7 @@ }; }; - reserved-memory { + reserved_memory: reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; From d19c8ea72a8686680d4bd455b55c4e931b770ccb Mon Sep 17 00:00:00 2001 From: Sarat Addepalli Date: Thu, 18 Jun 2026 12:55:09 +0530 Subject: [PATCH 0462/1058] FROMLIST: arm64: dts: qcom: qcm6490-idp: add and enable IPA node Enable IPA and ensure ipa apps loads the gsi firmware because modem doesn't support IPA FW loading. Link: https://lore.kernel.org/all/20260618124700.2001191-1-sarat.addepalli@oss.qualcomm.com/ Signed-off-by: Sarat Addepalli Signed-off-by: Pavan Kumar M Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 53c9689ae63c1..999862932e3ed 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -614,6 +614,13 @@ firmware-name = "qcom/qcm6490/a660_zap.mbn"; }; +&ipa { + qcom,gsi-loader = "self"; + memory-region = <&ipa_fw_mem>; + firmware-name = "qcom/qcm6490/ipa_fws.mbn"; + status = "okay"; +}; + &lpass_rx_macro { status = "okay"; }; From d70580362b1b5c9d8db75e08b810c8a9c8358fc3 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 14 May 2026 19:55:47 +0530 Subject: [PATCH 0463/1058] FROMLIST: dt-bindings: arm: Document reboot mode magic Add bindings to describe vendor-specific reboot modes. Values here correspond to valid parameters to vendor-specific reset types in PSCI SYSTEM_RESET2 call. Reviewed-by: Bartosz Golaszewski Reviewed-by: Rob Herring (Arm) Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20260514-arm-psci-system_reset2-vendor-reboots-v22-6-28a5bde07483@oss.qualcomm.com --- .../devicetree/bindings/arm/psci.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 6e2e0c5518411..5fdcbf331ea56 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -98,6 +98,26 @@ properties: [1] Kernel documentation - ARM idle states bindings Documentation/devicetree/bindings/cpu/idle-states.yaml + reboot-mode: + type: object + $ref: /schemas/power/reset/reboot-mode.yaml# + unevaluatedProperties: false + properties: + # "mode-normal" is just SYSTEM_RESET + mode-normal: false + patternProperties: + "^mode-.*$": + minItems: 1 + maxItems: 2 + description: | + Describes a vendor-specific reset type. The string after "mode-" + maps a reboot mode to the parameters in the PSCI SYSTEM_RESET2 call. + + Parameters are named mode-xxx = , where xxx is the + name of the magic reboot mode, type corresponds to the reset_type + and the values should be provided as per the PSCI SYSTEM_RESET2 + specs. The cookie value is optional and defaulted to zero. + patternProperties: "^power-domain-": $ref: /schemas/power/power-domain.yaml# @@ -137,6 +157,15 @@ allOf: required: - cpu_off - cpu_on + - if: + not: + properties: + compatible: + contains: + const: arm,psci-1.0 + then: + properties: + reboot-mode: false additionalProperties: false @@ -260,4 +289,17 @@ examples: domain-idle-states = <&cluster_ret>, <&cluster_pwrdn>; }; }; + + - |+ + + // Case 5: SYSTEM_RESET2 vendor resets + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + reboot-mode { + mode-edl = <0x80000000 1>; + mode-bootloader = <0x80010001 2>; + }; + }; ... From a3abff0ed93da426c683ccd620d99afb93d039ce Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2026 16:49:34 +0200 Subject: [PATCH 0464/1058] i2c: mpc: Fix timeout calculations At first glance the harmless cleanup of the driver does nothing bad. However, as the operator precedence list states the '*' (multiplication) and '/' division operators have order 5 with left-to-right associativity the *= has order 17 and associativity right-to-left. It wouldn't be a problem to replace foo = foo * HZ / 1000000; with foo *= HZ / 1000000; if HZ constant is in Hertz. The problem is that in the Linux kernel HZ is defined in jiffy units, which is order of magnitude smaller than a million. That's why operator precedence has a crucial role here. Fix the regression by reverting pre-optimized calculations. Fixes: be40a3ae719f ("i2c: mpc: Use of_property_read_u32 instead of of_get_property") Signed-off-by: Andy Shevchenko Cc: # v6.4+ Reviewed-by: Chris Packham Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260618144934.3249950-1-andriy.shevchenko@linux.intel.com --- drivers/i2c/busses/i2c-mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 28c5c5c1fb7a6..a21fa45bd64c4 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -844,7 +844,7 @@ static int fsl_i2c_probe(struct platform_device *op) "fsl,timeout", &mpc_ops.timeout); if (!result) { - mpc_ops.timeout *= HZ / 1000000; + mpc_ops.timeout = mpc_ops.timeout * HZ / 1000000; if (mpc_ops.timeout < 5) mpc_ops.timeout = 5; } else { From 216fa0d1486fc69c8164719e8d49ab6a67f27038 Mon Sep 17 00:00:00 2001 From: Mingyu Wang <25181214217@stu.xidian.edu.cn> Date: Tue, 12 May 2026 17:35:34 +0800 Subject: [PATCH 0465/1058] i2c: i801: fix hardware state machine corruption in error path A severe livelock and subsequent Hung Task panic were observed in the i2c-i801 driver during concurrent Fuzzing. The crash is caused by an unconditional hardware register cleanup in the error handling path of i801_access(). When i801_check_pre() fails (e.g., returning -EBUSY because the SMBus controller is actively used by BIOS/ACPI), the kernel does not actually acquire the hardware ownership. However, the code jumps to the 'out' label and executes: iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv)); This forcefully clears the INUSE_STS lock and resets the hardware status flags without owning the controller. Doing so interrupts ongoing BIOS/ACPI transactions and totally corrupts the SMBus hardware state machine. Consequently, all subsequent i801_access() calls fail at the pre-check stage, triggering an endless stream of "SMBus is busy, can't use it!" error logs. Over a slow serial console, this printk flood monopolizes the CPU (Console Livelock), starving other processes trying to acquire the mmap_lock down_read semaphore, ultimately triggering the hung task watchdog. Fix this by moving the 'out' label below the hardware register cleanup. If i801_check_pre() fails, we safely bypass the iowrite8() and only release the software locks (pm_runtime and mutex), strictly adhering to the rule of not releasing resources that were never acquired. Fixes: 1f760b87e54c ("i2c: i801: Call i801_check_pre() from i801_access()") Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> Cc: # v6.3+ Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260512093534.348655-1-w15303746062@163.com --- drivers/i2c/busses/i2c-i801.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 32a3cef02c7b5..b29c99ed38839 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -931,13 +931,13 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, */ if (hwpec) iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv)); -out: /* * Unlock the SMBus device for use by BIOS/ACPI, * and clear status flags if not done already. */ iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv)); +out: pm_runtime_put_autosuspend(&priv->pci_dev->dev); mutex_unlock(&priv->acpi_lock); return ret; From 1f44e993a91e2f885f3a388f87b55c74cbc5b9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Mon, 15 Jun 2026 10:37:26 -0300 Subject: [PATCH 0466/1058] ALSA: compress: Fix task creation error unwind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_compr_task_new() allocates the driver task before validating the returned DMA buffers and reserving file descriptors. When either of those later steps fails, the core frees its task wrapper and DMA-buffer references without calling the driver's task_free() callback. Any driver resources allocated by task_create() are therefore leaked. The dual-fd allocation path also jumps to cleanup without storing the negative get_unused_fd_flags() result in retval. Since retval still contains the successful task_create() return value, TASK_CREATE can incorrectly report success although the task was discarded. Preserve the fd allocation errors and call task_free() when failure occurs after a successful task_create() callback. Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode") Fixes: 3d3f43fab4cf ("ALSA: compress_offload: improve file descriptors installation for dma-buf") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260615-alsa-compress-task-unwind-v1-1-39e8ad3ddb27@gmail.com Signed-off-by: Takashi Iwai --- sound/core/compress_offload.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index fd63d219bf866..ea699491f0c36 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1083,15 +1083,18 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_ file descriptors are allocated before fd_install() */ if (!task->input || !task->input->file || !task->output || !task->output->file) { retval = -EINVAL; - goto cleanup; + goto free_driver_task; } fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC); - if (fd_i < 0) - goto cleanup; + if (fd_i < 0) { + retval = fd_i; + goto free_driver_task; + } fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC); if (fd_o < 0) { + retval = fd_o; put_unused_fd(fd_i); - goto cleanup; + goto free_driver_task; } /* keep dmabuf reference until freed with task free ioctl */ get_dma_buf(task->input); @@ -1103,6 +1106,8 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_ list_add_tail(&task->list, &stream->runtime->tasks); stream->runtime->total_tasks++; return 0; +free_driver_task: + stream->ops->task_free(stream, task); cleanup: snd_compr_task_free(task); return retval; From 08f8dc088f21cb218eb134fd1c8bd5fd0ffd04f2 Mon Sep 17 00:00:00 2001 From: Galen Hassen Date: Tue, 16 Jun 2026 10:32:57 -0700 Subject: [PATCH 0467/1058] ALSA: hda/conexant: Add pin config quirk for Lenovo IdeaPad Slim 5 16AKP10 The Lenovo IdeaPad Slim 5 16AKP10 (PCI SSID 17aa:38b6) uses the Conexant SN6140 codec. The internal microphone is on pin 0x1a but the BIOS configures it with pin default 0x95a60120, which includes a jack detection bit that causes the kernel to treat it as an unplugged external mic rather than a fixed internal mic. Add a pin config quirk that overrides pin 0x1a to 0x95a60130, setting the connectivity bits to indicate a fixed/always-connected device. This allows the internal microphone to be correctly identified and used. Signed-off-by: Galen Hassen Link: https://patch.msgid.link/20260616173257.37373-1-rwekyes@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/conexant.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c index e3b6aaabe3a9c..3d92262763f62 100644 --- a/sound/hda/codecs/conexant.c +++ b/sound/hda/codecs/conexant.c @@ -291,6 +291,7 @@ enum { CXT_FIXUP_HEADSET_MIC, CXT_FIXUP_HP_MIC_NO_PRESENCE, CXT_PINCFG_SWS_JS201D, + CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10, CXT_PINCFG_TOP_SPEAKER, CXT_FIXUP_HP_A_U, CXT_FIXUP_ACER_SWIFT_HP, @@ -826,6 +827,12 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = { {} }; +/* Lenovo IdeaPad Slim 5 16AKP10 with SN6140 */ +static const struct hda_pintbl cxt_pincfg_lenovo_ideapad_slim5_16akp10[] = { + { 0x1a, 0x95a60130 }, /* Internal mic, fixed/always-connected */ + {} +}; + /* SuoWoSi/South-holding JS201D with sn6140 */ static const struct hda_pintbl cxt_pincfg_sws_js201d[] = { { 0x16, 0x03211040 }, /* hp out */ @@ -1006,6 +1013,10 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_PINS, .v.pins = cxt_pincfg_sws_js201d, }, + [CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10] = { + .type = HDA_FIXUP_PINS, + .v.pins = cxt_pincfg_lenovo_ideapad_slim5_16akp10, + }, [CXT_PINCFG_TOP_SPEAKER] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -1114,6 +1125,7 @@ static const struct hda_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD), + SND_PCI_QUIRK(0x17aa, 0x38b6, "Lenovo IdeaPad Slim 5 16AKP10", CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10), SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), From 23ec67d207a7e7d2466f2a5b38f358b569f30892 Mon Sep 17 00:00:00 2001 From: Xu Rao Date: Tue, 16 Jun 2026 19:59:16 +0800 Subject: [PATCH 0468/1058] ALSA: usb-audio: qcom: Free sideband sg_table objects The Qualcomm USB audio offload driver obtains an endpoint transfer-ring table by calling xhci_sideband_get_endpoint_buffer(). This getter passes the endpoint ring to xhci_ring_to_sgtable(), which allocates the outer struct sg_table with kzalloc_obj(*sgt). The event-ring path is equivalent: xhci_sideband_get_event_buffer() also returns the result of xhci_ring_to_sgtable(). Inside xhci_ring_to_sgtable(), sg_alloc_table_from_pages() separately allocates the scatterlist storage referenced by sgt->sgl. The returned object therefore has two allocation layers: the outer struct sg_table and its internal scatterlist storage. The Qualcomm caller only invokes sg_free_table(sgt). sg_free_table() releases the scatterlist storage owned by the table, but it does not free the separately allocated outer struct sg_table. The local sgt pointer is then discarded, so every successful endpoint or event-ring query leaks the outer object. Call kfree(sgt) after sg_free_table(sgt) in both setup paths, after the required page and DMA addresses have been copied out. Fixes: 326bbc348298 ("ALSA: usb-audio: qcom: Introduce QC USB SND offloading support") Signed-off-by: Xu Rao Link: https://patch.msgid.link/90B353283AA150C4+20260616115916.1222915-1-raoxu@uniontech.com Signed-off-by: Takashi Iwai --- sound/usb/qcom/qc_audio_offload.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index a3f90cc7c6cad..436d6821c5c97 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1160,6 +1160,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs, tr_pa = page_to_phys(pg); mem_info->dma = sg_dma_address(sgt->sgl); sg_free_table(sgt); + kfree(sgt); /* data transfer ring */ iova = uaudio_iommu_map_pa(MEM_XFER_RING, dma_coherent, tr_pa, @@ -1229,6 +1230,7 @@ static int uaudio_event_ring_setup(struct snd_usb_substream *subs, er_pa = page_to_phys(pg); mem_info->dma = sg_dma_address(sgt->sgl); sg_free_table(sgt); + kfree(sgt); iova = uaudio_iommu_map_pa(MEM_EVENT_RING, dma_coherent, er_pa, PAGE_SIZE); From 27e3cc1fdedb1ebfe3f4fe7de5fff1d36c8159dd Mon Sep 17 00:00:00 2001 From: Ai Chao Date: Wed, 17 Jun 2026 10:52:34 +0800 Subject: [PATCH 0469/1058] ALSA: usb-audio: Add quirk flags for SC13A The SC13A ( VID 0x1ff7, PID 0x0f81) not support reading the current sample rate and results in an error message printed to kmsg. Set QUIRK_FLAG_GET_SAMPLE_RATE to skip the sample rate check. Quirky device sample: usb 3-5.2.4.1: new high-speed USB device number 11 using xhci_hcd usb 3-5.2.4.1: New USB device found, idVendor=1ff7, idProduct=0f81 usb 3-5.2.4.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 3-5.2.4.1: Product: SC13A usb 3-5.2.4.1: Manufacturer: Linux Foundation usb 3-5.2.4.1: SerialNumber: 000002 usb 3-5.2.4.1: Found UVC 1.50 device SC13A (1ff7:0f81) usb 3-5.2.4.1: 3:1: cannot get freq at ep 0x86 usb 3-5.2.4.1: Warning! Unlikely big volume range (=4096), cval->res is probably wrong. usb 3-5.2.4.1: [5] FU [Mic Capture Volume] ch = 1, val = 0/4096/1 usbcore: registered new interface driver snd-usb-audio usb 3-5.2.4.1: 3:1: cannot get freq at ep 0x86 usb 3-5.2.4.1: 3:1: cannot get freq at ep 0x86 Signed-off-by: Ai Chao Link: https://patch.msgid.link/20260617025234.3344935-1-aichao@kylinos.cn Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 30f6d572e4d1b..1cb588691e16d 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2413,6 +2413,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), + DEVICE_FLG(0x1ff7, 0x0f81, /* SC13A Webcam */ + QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ From d367e90d324b7451e4c2a1792302acd23454c36b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 17 Jun 2026 08:42:18 +0200 Subject: [PATCH 0470/1058] ALSA: sh: Use more common error handling code in snd_aica_probe() Use an additional label so that a bit of exception handling can be better reused at the end of this function implementation. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Link: https://patch.msgid.link/47413de1-015b-4543-8e8c-25e41dfa9e39@web.de Signed-off-by: Takashi Iwai --- sound/sh/aica.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 9438c3a68ee9e..8196e1bf04164 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -564,10 +564,9 @@ static int snd_aica_probe(struct platform_device *devptr) return -ENOMEM; err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER, THIS_MODULE, 0, &dreamcastcard->card); - if (unlikely(err < 0)) { - kfree(dreamcastcard); - return err; - } + if (unlikely(err < 0)) + goto free_card; + strscpy(dreamcastcard->card->driver, "snd_aica"); strscpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); strscpy(dreamcastcard->card->longname, @@ -593,6 +592,7 @@ static int snd_aica_probe(struct platform_device *devptr) return 0; freedreamcast: snd_card_free(dreamcastcard->card); +free_card: kfree(dreamcastcard); return err; } From 6c10215d4f4d71a820c6284e3476463a8eb9d52c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 17 Jun 2026 11:29:43 +0100 Subject: [PATCH 0471/1058] ALSA: pcm: fix __le32 cast warning in snd_pcm_set_sync_per_card In snd_pcm_set_sync_per_card() the le32 value is written to an u32 instead of an __le32 pointer. Fix the following warning by fixing the type: sound/soc/soc-pcm.c:2166:9: warning: incorrect type in argument 7 (different base types) sound/soc/soc-pcm.c:2166:9: expected int sound/soc/soc-pcm.c:2166:9: got restricted snd_pcm_format_t Signed-off-by: Ben Dooks Link: https://patch.msgid.link/20260617102943.893950-1-ben.dooks@codethink.co.uk Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index fe597f7d522de..4d665b4148d70 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -545,7 +545,7 @@ void snd_pcm_set_sync_per_card(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, const unsigned char *id, unsigned int len) { - *(__u32 *)params->sync = cpu_to_le32(substream->pcm->card->number); + *(__le32 *)params->sync = cpu_to_le32(substream->pcm->card->number); len = min(12, len); memcpy(params->sync + 4, id, len); memset(params->sync + 4 + len, 0, 12 - len); From eb44de981774741ce2d7117a811e6ee3719e80a3 Mon Sep 17 00:00:00 2001 From: Maoyi Xie Date: Thu, 18 Jun 2026 14:03:15 +0800 Subject: [PATCH 0472/1058] ALSA: caiaq: fix out-of-bounds read in the Traktor Kontrol S4 input parser snd_usb_caiaq_tks4_dispatch() decodes the Traktor Kontrol S4 input stream in fixed 16-byte (TKS4_MSGBLOCK_SIZE) message blocks. On every iteration it advances buf and subtracts the block size while looping on "while (len)". len is urb->actual_length. That value is supplied by the device and is not guaranteed to be a multiple of 16. When a final short block leaves len between 1 and 15, the loop runs once more, reads up to buf[15], and then does "len -= TKS4_MSGBLOCK_SIZE". As len is unsigned this underflows to a huge value. The loop then keeps iterating and walking buf far past the end of the 512-byte ep4_in_buf, reading out of bounds until a bogus block id happens to be hit. Iterate only while a full message block is available. This stops the unsigned underflow and silently drops any trailing partial block, which carries no complete control value anyway. The sibling endpoint-4 parsers are not affected. The Traktor Kontrol X1 and Maschine arms in snd_usb_caiaq_ep4_reply_dispatch() floor urb->actual_length before dispatching. Fixes: 15c5ab607045 ("ALSA: snd-usb-caiaq: Add support for Traktor Kontrol S4") Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie Link: https://patch.msgid.link/178176259547.3343534.2724779296835237429@maoyixie.com Signed-off-by: Takashi Iwai --- sound/usb/caiaq/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c index 5c70fdf61cc13..2db4d1332df1c 100644 --- a/sound/usb/caiaq/input.c +++ b/sound/usb/caiaq/input.c @@ -330,7 +330,7 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *cdev, { struct device *dev = caiaqdev_to_dev(cdev); - while (len) { + while (len >= TKS4_MSGBLOCK_SIZE) { unsigned int i, block_id = (buf[0] << 8) | buf[1]; switch (block_id) { From 70253b5af4f82904385a445ff4d1459637e661f7 Mon Sep 17 00:00:00 2001 From: Maoyi Xie Date: Thu, 18 Jun 2026 14:03:15 +0800 Subject: [PATCH 0473/1058] ALSA: caiaq: bound the length in the EP1 input parsers snd_caiaq_input_read_erp() and snd_caiaq_input_read_io() can be reached from snd_usb_caiaq_input_dispatch(). They read fixed byte offsets from the reply buffer without checking the reported length. On a short reply they decode stale bytes left from a previous, longer report and feed them to the input layer. This is not an out-of-bounds access. Every offset is a compile-time driver constant. The largest is buf[21] in the Maschine ERP case. The EP1 transfer buffer ep1_in_buf is EP1_BUFSIZE (64) bytes, and the USB core caps actual_length at 64, so a short reply only reads in-bounds stale data. Acting on data the device did not send is still wrong, so bail out per usb_id case when the reply is shorter than the bytes that case consumes. read_erp: AK1 needs 2 bytes, Kore needs 16, Maschine needs 22. read_io: the Kore case needs 5 bytes (buf[4]) and the Traktor Kontrol X1 case needs 7 (buf[5]/buf[6]). The preceding key bit loop is already bounded by "i < len * 8" and is left untouched. snd_caiaq_input_read_analog() and snd_usb_caiaq_maschine_dispatch() are not changed. Their callers already floor the reply length. Suggested-by: Takashi Iwai Signed-off-by: Maoyi Xie Link: https://patch.msgid.link/178176259547.3343534.6659489917322808916@maoyixie.com Signed-off-by: Takashi Iwai --- sound/usb/caiaq/input.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c index 2db4d1332df1c..eabbf41fdfb2b 100644 --- a/sound/usb/caiaq/input.c +++ b/sound/usb/caiaq/input.c @@ -237,12 +237,16 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev, switch (cdev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + if (len < 2) + return; i = decode_erp(buf[0], buf[1]); input_report_abs(input_dev, ABS_X, i); input_sync(input_dev); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + if (len < 16) + return; i = decode_erp(buf[7], buf[5]); input_report_abs(input_dev, ABS_HAT0X, i); i = decode_erp(buf[12], buf[14]); @@ -263,6 +267,8 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev, break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): + if (len < 22) + return; /* 4 under the left screen */ input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20])); input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14])); @@ -308,9 +314,13 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *cdev, switch (cdev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + if (len < 5) + return; input_report_abs(cdev->input_dev, ABS_MISC, 255 - buf[4]); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): + if (len < 7) + return; /* rotary encoders */ input_report_abs(cdev->input_dev, ABS_X, buf[5] & 0xf); input_report_abs(cdev->input_dev, ABS_Y, buf[5] >> 4); From a8f57565b4a98c3af9bd663028965d2ea6ec29d9 Mon Sep 17 00:00:00 2001 From: Haowen Tu Date: Thu, 18 Jun 2026 15:54:31 +0800 Subject: [PATCH 0474/1058] ALSA: hda/realtek: Add headset mic quirk for Acer S40-54 Acer S40-54 with ALC256 does not restore headset mic detection properly after S4 resume. After resume, headset plug events may no longer update the headset mic state, leaving the headset microphone unavailable. The system uses subsystem ID 1025:161f. Applying the existing ALC256_FIXUP_ACER_MIC_NO_PRESENCE fixup restores headset mic detection on this machine. Add a machine-specific quirk for this system. Signed-off-by: Haowen Tu Link: https://patch.msgid.link/20260618075431.1116988-1-tuhaowen@uniontech.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 5d09baa6d32e9..d209efdb82724 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -6807,6 +6807,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC287_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x161f, "Acer S40-54", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), From fa00f95807ba217e3adeb58c5df9ff3f5c78f64f Mon Sep 17 00:00:00 2001 From: Michael Bommarito Date: Wed, 17 Jun 2026 22:51:25 -0400 Subject: [PATCH 0475/1058] ALSA: usb-audio: qcom: reject stream disable with no active interface handle_uaudio_stream_req() resolves an interface index with info_idx_from_ifnum(), which returns -EINVAL when no interface matches. The enable branch and the response: cleanup label both guard against a negative index, but the disable branch does not: it forms info = &uadev[pcm_card_num].info[info_idx] and dereferences it. uadev[].info is a pointer allocated only when a stream is first enabled, so a negative info_idx on the disable path is unsafe in two ways: - If the card was never enabled, .info is NULL and &info[-EINVAL] is a wild pointer; reading info->data_ep_pipe faults (kernel oops). - If the card was enabled at least once (.info allocated) and the disable names an interface that does not match, &info[-EINVAL] points before the allocation; info->data_ep_pipe / info->sync_ep_pipe are an out-of-bounds slab read and, when non-zero, an out-of-bounds 4-byte write (both pipe fields are cleared to 0). That is memory corruption, not just a NULL dereference. The request is reachable from unprivileged local userspace over AF_QIPCRTR. Reject a disable request with no resolved interface, matching the guard the enable path already has. Fixes: 326bbc348298a ("ALSA: usb-audio: qcom: Introduce QC USB SND offloading support") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito Link: https://patch.msgid.link/20260618025126.1862954-2-michael.bommarito@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/qcom/qc_audio_offload.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 436d6821c5c97..3b05dadbbeae2 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1642,6 +1642,11 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, subs->opened = 0; } } else { + if (info_idx < 0) { + ret = -EINVAL; + goto response; + } + info = &uadev[pcm_card_num].info[info_idx]; if (info->data_ep_pipe) { ep = usb_pipe_endpoint(uadev[pcm_card_num].udev, From b6874fdba1167fa3c8cee9c042bd3aa91139ab37 Mon Sep 17 00:00:00 2001 From: Michael Bommarito Date: Wed, 17 Jun 2026 22:51:26 -0400 Subject: [PATCH 0476/1058] ALSA: usb-audio: qcom: clear opened when stream enable fails On enable, subs->opened is set before the service_interval is validated; an invalid interval jumps to the response label without clearing it, so the substream is wedged at -EBUSY until a disable or disconnect. Clear subs->opened on the enable error path. Fixes: 326bbc348298a ("ALSA: usb-audio: qcom: Introduce QC USB SND offloading support") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito Link: https://patch.msgid.link/20260618025126.1862954-3-michael.bommarito@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/qcom/qc_audio_offload.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 3b05dadbbeae2..3a586fd16e729 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1620,8 +1620,13 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle, if (req_msg->service_interval_valid) { ret = get_data_interval_from_si(subs, req_msg->service_interval); - if (ret == -EINVAL) + if (ret == -EINVAL) { + if (req_msg->enable) { + guard(mutex)(&chip->mutex); + subs->opened = 0; + } goto response; + } datainterval = ret; } From bafb82cccaf8bfc1d90407e4cdcc0aae3634e5b1 Mon Sep 17 00:00:00 2001 From: Jean-Louis Colaco Date: Thu, 18 Jun 2026 13:32:02 +0200 Subject: [PATCH 0477/1058] ALSA: usb-audio: Add quirk for YAMAHA CDS3000 This quirk is identical to the one for the Yamaha Steinberg UR22, here applied to a CD player that also uses the Steinberg USB interface. This quirk is necessary to avoid sporadic "clic" noise when using the DAC of the player. Signed-off-by: Jean-Louis Colaco Link: https://patch.msgid.link/20260618113202.8363-1-jean-louis.colaco@orange.fr Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 97f28c53d2015..71444c2898b4b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -390,6 +390,20 @@ YAMAHA_DEVICE(0x105d, NULL), } } }, +{ + USB_DEVICE(0x0499, 0x150d), + QUIRK_DRIVER_INFO { + /* .vendor_name = "Yamaha", */ + /* .product_name = "CDS3000", */ + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END + } + } +}, { USB_DEVICE(0x0499, 0x1718), QUIRK_DRIVER_INFO { From c6c4c6c008e22eee7e9ad2fda7d2bba310d07ef3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 18 Jun 2026 12:24:36 +0200 Subject: [PATCH 0478/1058] ALSA: emu10k1: Use common error handling code in snd_emu10k1_playback_open() Use an additional label so that a bit of exception handling can be better reused at the end of this function implementation. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Link: https://patch.msgid.link/d709474d-62b0-4f7e-9011-a0f716b35383@web.de Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emupcm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 9023f3444d205..b8749e0131adc 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -1181,19 +1181,17 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_playback; err = snd_emu10k1_playback_set_constraints(runtime); - if (err < 0) { - kfree(epcm); - return err; - } + if (err < 0) + goto free_epcm; + if (emu->card_capabilities->emu_model) sample_rate = emu->emu1010.word_clock; else sample_rate = 48000; err = snd_pcm_hw_rule_noresample(runtime, sample_rate); - if (err < 0) { - kfree(epcm); - return err; - } + if (err < 0) + goto free_epcm; + mix = &emu->pcm_mixer[substream->number]; for (i = 0; i < 8; i++) mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i; @@ -1204,6 +1202,10 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) mix->epcm = epcm; snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1); return 0; + +free_epcm: + kfree(epcm); + return err; } static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream) From b64192d0b8d25d0e0e826bf41f64b1e106db246b Mon Sep 17 00:00:00 2001 From: Cen Zhang Date: Fri, 19 Jun 2026 01:00:10 +0800 Subject: [PATCH 0479/1058] ALSA: usb-audio: Kill MIDI 2.0 URBs before freeing endpoints MIDI 2.0 input URBs are started during snd_usb_midi_v2_create(). A later setup failure can still jump to snd_usb_midi_v2_free(), which currently frees each endpoint and its coherent URB buffers without first stopping the submitted URBs. A completion can then dereference the embedded URB context and endpoint state after they have been freed, or try to resubmit from the stale endpoint. This was observed as a KASAN slab-use-after-free in input_urb_complete(). The buggy scenario involves two paths, with each column showing the order within that path: probe error path: USB completion path: 1. start_input_streams() submits 1. The HCD still owns a input URBs. submitted input URB. 2. A later setup helper returns 2. input_urb_complete() runs an error. with urb->context in ep. 3. snd_usb_midi_v2_free() frees 3. The completion reads ep endpoint storage and URB buffers. state and can requeue URBs. Make the endpoint destructor follow the same teardown ordering used for disconnect when the endpoint has not already been disconnected: publish ep->disconnected, kill the URBs synchronously, and drain the endpoint before freeing URB buffers and endpoint storage. The guard avoids repeating the stop sequence after the normal snd_usb_midi_v2_disconnect_all() path, while still synchronizing the direct MIDI 2.0 create-error free path. Validation reproduced this kernel report: BUG: KASAN: slab-use-after-free in input_urb_complete+0x37/0x1b0 Workqueue: usb_hub_wq hub_event RIP: 0010:_raw_spin_unlock_irq+0x2e/0x50 Read of size 8 Call trace: dump_stack_lvl+0x77/0xb0 print_report+0xce/0x5f0 input_urb_complete+0x37/0x1b0 (sound/usb/midi2.c:186) srso_alias_return_thunk+0x5/0xfbef5 __virt_addr_valid+0x19f/0x330 kasan_report+0xe0/0x110 __usb_hcd_giveback_urb+0x112/0x1d0 dummy_timer+0xaaa/0x19a0 lock_is_held_type+0x9a/0x110 __lock_acquire+0x467/0x28b0 mark_held_locks+0x40/0x70 _raw_spin_unlock_irqrestore+0x44/0x60 lockdep_hardirqs_on_prepare+0xbb/0x1a0 __hrtimer_run_queues+0x101/0x520 hrtimer_run_softirq+0xd0/0x130 handle_softirqs+0x15b/0x670 __irq_exit_rcu+0xd0/0x170 irq_exit_rcu+0xe/0x20 sysvec_apic_timer_interrupt+0x6c/0x80 asm_sysvec_apic_timer_interrupt+0x1a/0x20 Fixes: d9c99876868c ("ALSA: usb-audio: Create UMP blocks from USB MIDI GTBs") Assisted-by: Codex:gpt-5.5 Signed-off-by: Cen Zhang Link: https://patch.msgid.link/20260618170010.191433-1-zzzccc427@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/midi2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c index 04aeb9052f139..3ec6332917726 100644 --- a/sound/usb/midi2.c +++ b/sound/usb/midi2.c @@ -470,6 +470,11 @@ static int create_midi2_endpoint(struct snd_usb_midi2_interface *umidi, static void free_midi2_endpoint(struct snd_usb_midi2_endpoint *ep) { list_del(&ep->list); + if (!ep->disconnected) { + ep->disconnected = 1; + kill_midi_urbs(ep, false); + drain_urb_queue(ep); + } free_midi_urbs(ep); kfree(ep); } From 5816ed288fcd608dfa4c97f0f741bb562241878f Mon Sep 17 00:00:00 2001 From: Ramcharan Rajpurohit Date: Fri, 19 Jun 2026 11:54:35 +0530 Subject: [PATCH 0480/1058] ALSA: hda/realtek: Enable mute LED on HP EliteBook 840 G6 The HP EliteBook 840 G6 (PCI SSID 103c:854d) has an ALC215 codec whose mic-mute and audio-mute LEDs are wired to the same GPIOs as the already supported EliteBook 830 G6 and 840 G7. Without a matching quirk the LEDs are never registered, so the front-panel mic-mute LED stays permanently lit and does not track the mute state. Apply ALC285_FIXUP_HP_GPIO_LED, mirroring the sibling EliteBook entries. With this fixup the codec registers an "hda::micmute" LED class device and the LED correctly follows the capture-mute state. This was verified on the affected machine by forcing the same fixup at runtime via snd_sof_intel_hda_generic.hda_model=103c:8548, which made the LED work as expected. Signed-off-by: Ramcharan Rajpurohit Link: https://patch.msgid.link/20260619062435.26256-1-b23ci1032@iitj.ac.in Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index d209efdb82724..2df491335a760 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -6987,6 +6987,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x854d, "HP EliteBook 840 G6", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x856a, "HP Pavilion 15-cs1xxx", ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B), SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11), SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360), From 08bfbaa09f1d185286f836126fb2a12836047044 Mon Sep 17 00:00:00 2001 From: Chris Aherin Date: Sun, 21 Jun 2026 19:12:10 -0500 Subject: [PATCH 0481/1058] ALSA: hda/realtek: Add quirk for Lenovo Yoga 7 16IAP7 The Yoga 7 16IAP7 (board LNVNB161216, codec SSID 17aa:386a) has pin complex 0x17 (bass speakers) wrongly reported as unconnected, causing only one of four speaker pins (0x14) to be configured and resulting in mono/tinny audio. SOF corrupts the PCI subsystem ID to 17aa:0000, preventing SND_PCI_QUIRK from matching. HDA_CODEC_QUIRK is used instead, which matches against codec->core.subsystem_id read directly from the HDA codec register and unaffected by the SOF bug. Applies ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, the same fixup used for the Yoga 7 14IAL7, which corrects pin 0x17's default configuration and enables both speaker pairs. Signed-off-by: Chris Aherin Link: https://patch.msgid.link/20260622001210.20553-1-chrisaherin@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 2df491335a760..c83c1654ed45c 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7755,6 +7755,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), + HDA_CODEC_QUIRK(0x17aa, 0x386a, "Lenovo Yoga 7 16IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), HDA_CODEC_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_SPEAKER2_TO_DAC1), HDA_CODEC_QUIRK(0x17aa, 0x38a8, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */ From e2898ecdc7b16b570c6eaa9fdc20b5165dda74c2 Mon Sep 17 00:00:00 2001 From: Dirk Su Date: Mon, 22 Jun 2026 15:20:04 +0800 Subject: [PATCH 0482/1058] ALSA: hda/realtek: Add LED fixup for HP EliteBook 6 G2i Laptops The HP EliteBook 6 G2i laptops requires specific LED control method ALC236_FIXUP_HP_GPIO_LED to work Signed-off-by: Dirk Su Link: https://patch.msgid.link/20260622072019.56351-1-dirk.su@canonical.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index c83c1654ed45c..e88ca720f4e51 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7328,6 +7328,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8f0e, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8f2d, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8f2e, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8f37, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8f38, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8f39, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8f3a, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8f3c, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8f3d, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8f40, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED), From 23b84d9670a1b0ec31c9ea9e42589cf5a138b727 Mon Sep 17 00:00:00 2001 From: Aaron Erhardt Date: Tue, 19 May 2026 17:49:48 +0200 Subject: [PATCH 0483/1058] ALSA: hda/realtek: Fix noisy mic for Clevo V6xxAW Add a PCI quirk to reduce the volume of the internal microphone to prevent extremely noisy signal. Signed-off-by: Aaron Erhardt Signed-off-by: Werner Sembach Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260519155047.106096-1-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index e88ca720f4e51..0d932f6ae3e88 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7603,6 +7603,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x5700, "Clevo X560WN[RST]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x6480, "Clevo V6xxAW", ALC245_FIXUP_CLEVO_NOISY_MIC), SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), From 7ee465bd9770a65ccd680faf512cfade9653c6fd Mon Sep 17 00:00:00 2001 From: "Geoffrey D. Bennett" Date: Tue, 23 Jun 2026 02:59:04 +0930 Subject: [PATCH 0484/1058] ALSA: FCP: Add Focusrite ISA C8X support Add USB PID 0x821e to the list of devices handled by the Focusrite Control Protocol (FCP) driver. Cc: stable@vger.kernel.org Signed-off-by: Geoffrey D. Bennett Link: https://patch.msgid.link/ajlw4HK+2RSW3nUl@m.b4.vu Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 628f841b04aae..f6f2bc8e97a7c 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -4526,6 +4526,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x1235, 0x821b): /* Focusrite Scarlett 16i16 4th Gen */ case USB_ID(0x1235, 0x821c): /* Focusrite Scarlett 18i16 4th Gen */ case USB_ID(0x1235, 0x821d): /* Focusrite Scarlett 18i20 4th Gen */ + case USB_ID(0x1235, 0x821e): /* Focusrite ISA C8X */ err = snd_fcp_init(mixer); break; From 46ad1cef7d9383b55541e441a4a46a9d7a1f2df6 Mon Sep 17 00:00:00 2001 From: HyeongJun An Date: Wed, 24 Jun 2026 08:38:40 +0900 Subject: [PATCH 0485/1058] ALSA: seq: Fix uninitialised heap leak in snd_seq_event_dup() snd_seq_event_dup() copies an incoming event into a pool cell and, in the UMP-enabled build, clears the trailing cell->ump.raw.extra word that the memcpy() did not cover. The guard deciding whether to clear it compares the copied size against sizeof(cell->event): memcpy(&cell->ump, event, size); if (size < sizeof(cell->event)) cell->ump.raw.extra = 0; For a legacy (non-UMP) event, size == sizeof(struct snd_seq_event) == sizeof(cell->event), so the condition is false and the extra word keeps stale data. The cell pool is allocated with kvmalloc() (not zeroed) and cells are reused via a free list, so that word holds uninitialised heap or leftover event data. When such a cell is delivered to a UMP client (client->midi_version > 0) that set SNDRV_SEQ_FILTER_NO_CONVERT -- so the legacy event reaches it unconverted -- snd_seq_read() reads it out as the larger struct snd_seq_ump_event and copies the stale word to user space, a 4-byte kernel heap infoleak to an unprivileged /dev/snd/seq client. Compare against sizeof(cell->ump) instead, so the trailing word is zeroed for every event shorter than the UMP cell. Fixes: 46397622a3fa ("ALSA: seq: Add UMP support") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: HyeongJun An Link: https://patch.msgid.link/20260623233841.853326-1-sammiee5311@gmail.com Signed-off-by: Takashi Iwai --- sound/core/seq/seq_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index ca9f6db0022c8..209b08c2a9408 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -364,7 +364,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, size = snd_seq_event_packet_size(event); memcpy(&cell->ump, event, size); #if IS_ENABLED(CONFIG_SND_SEQ_UMP) - if (size < sizeof(cell->event)) + if (size < sizeof(cell->ump)) cell->ump.raw.extra = 0; #endif From 7767e8c8b7227027e3e7ea8697ace9b470e0961c Mon Sep 17 00:00:00 2001 From: Oleg Kucheryavenko Date: Wed, 24 Jun 2026 22:13:01 +0300 Subject: [PATCH 0486/1058] ALSA: hda/realtek: Add quirk for Acer Nitro ANV15-41 The Acer Nitro ANV15-41 laptop with ALC245 codec does not detect the headset microphone in the combo jack by default. Apply the ALC2XX_FIXUP_HEADSET_MIC quirk to fix it. Signed-off-by: Oleg Kucheryavenko Link: https://patch.msgid.link/20260624191301.10162-1-oleg.kucheryavenko2018@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 0d932f6ae3e88..2a7a693ecedfd 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -6813,6 +6813,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x173a, "Acer Swift SFG14-73", ALC245_FIXUP_ACER_MICMUTE_LED), + SND_PCI_QUIRK(0x1025, 0x1758, "Acer Nitro ANV15-41", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), From 61065782d082c4d44bd888d224030e5aae3d3da8 Mon Sep 17 00:00:00 2001 From: Darvell Long Date: Wed, 24 Jun 2026 07:37:23 -0700 Subject: [PATCH 0487/1058] ALSA: usb-audio: avoid kobject path lookup in DualSense match The DualSense jack-detection input handler verifies that a matching input device belongs to the same physical controller by building kobject path strings for both the input device and the USB audio device, then comparing the path prefix. This was observed when a weak physical connection caused the controller to rapidly disconnect and reconnect. During that repeated hotplug, snd_dualsense_ih_match() can run while the controller's USB device is being disconnected. kobject_get_path() walks ancestor kobjects and dereferences their names; if the USB device kobject name is no longer valid, this can fault in strlen(): RIP: 0010:strlen+0x10/0x30 Call Trace: kobject_get_path+0x34/0x150 snd_dualsense_ih_match+0x49/0xd0 [snd_usb_audio] input_register_device+0x566/0x6a0 ps_probe+0xb89/0x1590 [hid_playstation] The same ownership check can be done without building kobject path strings. The input device is parented below the HID device, USB interface and USB device, so walking the input device parent chain and comparing against the mixer USB device preserves the check without dereferencing kobject names during disconnect. Fixes: 79d561c4ec04 ("ALSA: usb-audio: Add mixer quirk for Sony DualSense PS5") Cc: Assisted-by: Cute:gpt-5.5 Signed-off-by: Darvell Long Link: https://patch.msgid.link/20260624143723.2986353-1-contact@darvell.me Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f6f2bc8e97a7c..10792d26fa94a 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -577,46 +577,30 @@ static bool snd_dualsense_ih_match(struct input_handler *handler, { struct dualsense_mixer_elem_info *mei; struct usb_device *snd_dev; - char *input_dev_path, *usb_dev_path; - size_t usb_dev_path_len; - bool match = false; + struct device *parent; mei = container_of(handler, struct dualsense_mixer_elem_info, ih); snd_dev = mei->info.head.mixer->chip->dev; - input_dev_path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); - if (!input_dev_path) { - dev_warn(&snd_dev->dev, "Failed to get input dev path\n"); - return false; - } - - usb_dev_path = kobject_get_path(&snd_dev->dev.kobj, GFP_KERNEL); - if (!usb_dev_path) { - dev_warn(&snd_dev->dev, "Failed to get USB dev path\n"); - goto free_paths; - } - /* * Ensure the VID:PID matched input device supposedly owned by the * hid-playstation driver belongs to the actual hardware handled by - * the current USB audio device, which implies input_dev_path being - * a subpath of usb_dev_path. + * the current USB audio device. * * This verification is necessary when there is more than one identical * controller attached to the host system. + * + * The input device is registered below the HID device, USB interface and + * USB device, so compare the parent chain directly instead of building + * kobject path strings. This avoids dereferencing kobject names while the + * USB device hierarchy is being torn down during disconnect. */ - usb_dev_path_len = strlen(usb_dev_path); - if (usb_dev_path_len >= strlen(input_dev_path)) - goto free_paths; - - usb_dev_path[usb_dev_path_len] = '/'; - match = !memcmp(input_dev_path, usb_dev_path, usb_dev_path_len + 1); - -free_paths: - kfree(input_dev_path); - kfree(usb_dev_path); + for (parent = dev->dev.parent; parent; parent = parent->parent) { + if (parent == &snd_dev->dev) + return true; + } - return match; + return false; } static int snd_dualsense_ih_connect(struct input_handler *handler, From cc03d9bcccd6913be9a944d5a1430528f320d6da Mon Sep 17 00:00:00 2001 From: Kamlesh Chhetty Date: Mon, 22 Jun 2026 13:22:47 -0400 Subject: [PATCH 0488/1058] ALSA: hda: Add Lenovo Legion 7i 16IAX7 17AA3874 quirk Lenovo Legion 7i 16IAX7 systems with Realtek ALC287 codec SSID 17aa:3874 and CSC3551/CS35L41 speaker amps do not provide the required CS35L41 _DSD properties in ACPI. Without a quirk, cs35l41-hda fails probing the amps with missing cirrus,dev-index / Platform not supported errors, leaving the built-in speakers silent. This model is similar to the already-supported 17AA386F Legion 7i 16IAX7 variant. Add the Realtek ALC287 quirk to select ALC287_FIXUP_CS35L41_I2C_2 and add 17AA3874 to the CS35L41 property table using the same two-amp external-boost configuration. Tested on a Lenovo Legion 7 16IAX7 with Ubuntu 7.0.0-22-generic. Both CSC3551 CS35L41 amps probe and bind, firmware loads, calibration applies, built-in speaker playback works, and the cirrus,dev-index failure is gone. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221663 Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2157060 Signed-off-by: Kamlesh Chhetty Link: https://patch.msgid.link/20260622172247.19301-1-kamleshkc2002@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + sound/hda/codecs/side-codecs/cs35l41_hda_property.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 2a7a693ecedfd..71625394aa995 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7767,6 +7767,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { HDA_CODEC_QUIRK(0x17aa, 0x38a8, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), + SND_PCI_QUIRK(0x17aa, 0x3874, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C), diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda_property.c b/sound/hda/codecs/side-codecs/cs35l41_hda_property.c index 732ae534db360..416d7bf3e289c 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda_property.c +++ b/sound/hda/codecs/side-codecs/cs35l41_hda_property.c @@ -128,6 +128,7 @@ static const struct cs35l41_config cs35l41_config_table[] = { { "17AA3866", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, { "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, + { "17AA3874", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, { "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, @@ -554,6 +555,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { { "CSC3551", "17AA3866", generic_dsd_config }, { "CSC3551", "17AA386E", generic_dsd_config }, { "CSC3551", "17AA386F", generic_dsd_config }, + { "CSC3551", "17AA3874", generic_dsd_config }, { "CSC3551", "17AA3877", generic_dsd_config }, { "CSC3551", "17AA3878", generic_dsd_config }, { "CSC3551", "17AA38A9", generic_dsd_config }, From 06a327d2b824a02a00a521b6c07b76b039d48719 Mon Sep 17 00:00:00 2001 From: Xu Rao Date: Tue, 23 Jun 2026 15:13:08 +0800 Subject: [PATCH 0489/1058] ALSA: usb-audio: qcom: Free QMI handle qc_usb_audio_probe() allocates svc->uaudio_svc_hdl separately from the uaudio_qmi_svc object. qmi_handle_release() releases the resources owned by an initialized QMI handle, but does not free the memory containing the struct qmi_handle itself. The probe error path and the remove path currently release the handle and then free svc, losing the last pointer to the separately allocated handle. This leaks one struct qmi_handle on each affected probe unwind and on each successful probe/remove cycle. Free the handle after qmi_handle_release() in both paths. Signed-off-by: Xu Rao Link: https://patch.msgid.link/9108EC860F3F87DF+20260623071308.2549182-1-raoxu@uniontech.com Signed-off-by: Takashi Iwai --- sound/usb/qcom/qc_audio_offload.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index 3a586fd16e729..e4bfd43a2488b 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -1988,6 +1988,7 @@ static int qc_usb_audio_probe(struct auxiliary_device *auxdev, release_qmi: qc_usb_audio_cleanup_qmi_dev(); qmi_handle_release(svc->uaudio_svc_hdl); + kfree(svc->uaudio_svc_hdl); free_svc: kfree(svc); @@ -2012,6 +2013,7 @@ static void qc_usb_audio_remove(struct auxiliary_device *auxdev) qc_usb_audio_cleanup_qmi_dev(); qmi_handle_release(svc->uaudio_svc_hdl); + kfree(svc->uaudio_svc_hdl); kfree(svc); uaudio_svc = NULL; } From 99706679b38b05960f60378fba242b59ed62173a Mon Sep 17 00:00:00 2001 From: Maoyi Xie Date: Sun, 21 Jun 2026 23:09:07 +0800 Subject: [PATCH 0490/1058] ALSA: firewire: isight: bound the sample count to the packet payload isight_packet() takes the frame count from the device iso packet and checks it only against the device claimed iso length. count = be32_to_cpu(payload->sample_count); if (likely(count <= (length - 16) / 4)) isight_samples(isight, payload->samples, count); length is the iso header data_length. It can be up to 0xffff. So the gate allows a count up to about 16379. isight_samples() then copies count frames out of payload->samples into the PCM DMA buffer. payload->samples holds only 2 * MAX_FRAMES_PER_PACKET values. The device multiplexes two samples per frame. A count past MAX_FRAMES_PER_PACKET reads past the payload. A count past the buffer size writes past runtime->dma_area. The smallest PCM buffer is larger than MAX_FRAMES_PER_PACKET. Bounding the count to MAX_FRAMES_PER_PACKET keeps both the read and the write in range. A malicious or faulty Apple iSight on the FireWire bus reaches this during a normal capture. Add the MAX_FRAMES_PER_PACKET bound to the gate. Fixes: 3a691b28a0ca ("ALSA: add Apple iSight microphone driver") Suggested-by: Takashi Sakamoto Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie Link: https://patch.msgid.link/178205454729.1900991.7807310178296762772@maoyixie.com Signed-off-by: Takashi Iwai --- sound/firewire/isight.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 2b7f071d593b9..33c9dd48b3b0b 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -179,7 +179,8 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, if (likely(length >= 16 && payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) { count = be32_to_cpu(payload->sample_count); - if (likely(count <= (length - 16) / 4)) { + if (likely(count <= (length - 16) / 4 && + count <= MAX_FRAMES_PER_PACKET)) { total = be32_to_cpu(payload->sample_total); if (unlikely(total != isight->total_samples)) { if (!isight->first_packet) From 2a0001d549c0fa706e797a75b3655aaefd880434 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 16 Jun 2026 18:02:57 +0100 Subject: [PATCH 0491/1058] ASoC: qcom: q6apm: fix NULL pointer dereference in graph_callback When q6apm_free_fragments() is called it frees rx_data.buf/tx_data.buf and sets them to NULL under graph->lock. A late DSP buffer-done response can race with this: graph_callback() passes the !graph->ar_graph guard (not yet NULL), acquires the lock, but then dereferences a now-NULL buf pointer to read buf[token].phys, crashing at virtual address 0x10. Add a NULL check for buf inside the mutex-protected section in both the write-done (DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2) and read-done (DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2) handlers and bail out cleanly if buffers have already been freed. This problem is only shown up recently while apr bus was updated to process the commands per service rather from single global queue. Fixes: 5477518b8a0e ("ASoC: qdsp6: audioreach: add q6apm support") Cc: Stable@vger.kernel.org Assisted-by: Claude:claude-4-6-sonnet Reported-by: Val Packett Closes: https://lore.kernel.org/all/133ced18-1aa9-475d-80d8-6120678bdde4@packett.cool/ Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260616170257.9381-1-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 2e5b25b8d00fd..641d6d2432299 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -587,6 +587,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) token = hdr->token & APM_WRITE_TOKEN_MASK; done = data->payload; + if (!graph->rx_data.buf) { + mutex_unlock(&graph->lock); + break; + } phys = graph->rx_data.buf[token].phys; mutex_unlock(&graph->lock); /* token numbering starts at 0 */ @@ -609,6 +613,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) client_event = APM_CLIENT_EVENT_DATA_READ_DONE; mutex_lock(&graph->lock); rd_done = data->payload; + if (!graph->tx_data.buf) { + mutex_unlock(&graph->lock); + break; + } phys = graph->tx_data.buf[hdr->token].phys; mutex_unlock(&graph->lock); /* token numbering starts at 0 */ From 3dc658921e7d7a97d3f6473d6d2e7e21913b14d4 Mon Sep 17 00:00:00 2001 From: Nicolas Frattaroli Date: Wed, 17 Jun 2026 13:46:04 +0200 Subject: [PATCH 0492/1058] ASoC: rockchip: Drop problematic guard() changes This reverts commit f7fe9f707360 ("ASoC: rockchip: rockchip_sai: Use guard() for spin locks"). This is very noisy pointless churn that was not tested by the submitter, nor was it addressed to the driver's maintainer. It mixes unrelated whitespace changes (eliminating the blank line between the includes - why?) with hard to review diffs that add a whole indentation level to the function for no benefit, while also not following kernel code style by doing stuff like "ret == 0". The driver is better off without these changes, and they're not worth the time to validate whether they really do make no functional changes. Signed-off-by: Nicolas Frattaroli Link: https://patch.msgid.link/20260617-sai-revert-v1-1-e46adda2213b@collabora.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_sai.c | 262 +++++++++++++++--------------- 1 file changed, 133 insertions(+), 129 deletions(-) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index a195e96fed0ac..ed393e5034a49 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -18,6 +18,7 @@ #include #include #include + #include "rockchip_sai.h" #define DRV_NAME "rockchip-sai" @@ -215,12 +216,14 @@ static void rockchip_sai_xfer_clk_stop_and_wait(struct rk_sai_dev *sai, unsigned static int rockchip_sai_runtime_suspend(struct device *dev) { struct rk_sai_dev *sai = dev_get_drvdata(dev); + unsigned long flags; rockchip_sai_fsync_lost_detect(sai, 0); rockchip_sai_fsync_err_detect(sai, 0); - scoped_guard(spinlock_irqsave, &sai->xfer_lock) - rockchip_sai_xfer_clk_stop_and_wait(sai, NULL); + spin_lock_irqsave(&sai->xfer_lock, flags); + rockchip_sai_xfer_clk_stop_and_wait(sai, NULL); + spin_unlock_irqrestore(&sai->xfer_lock, flags); regcache_cache_only(sai->regmap, true); /* @@ -480,6 +483,7 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); unsigned int mask = 0, val = 0; unsigned int clk_gates; + unsigned long flags; int ret = 0; pm_runtime_get_sync(dai->dev); @@ -495,56 +499,56 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) sai->is_master_mode = false; break; default: - pm_runtime_put(dai->dev); - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; } - scoped_guard(spinlock_irqsave, &sai->xfer_lock) { - rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); - if (sai->initialized) { - if (sai->has_capture && sai->has_playback) - rockchip_sai_xfer_stop(sai, -1); - else if (sai->has_capture) - rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE); - else - rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK); - } else { - rockchip_sai_clear(sai, 0); - sai->initialized = true; - } + spin_lock_irqsave(&sai->xfer_lock, flags); + rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); + if (sai->initialized) { + if (sai->has_capture && sai->has_playback) + rockchip_sai_xfer_stop(sai, -1); + else if (sai->has_capture) + rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE); + else + rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK); + } else { + rockchip_sai_clear(sai, 0); + sai->initialized = true; + } - regmap_update_bits(sai->regmap, SAI_CKR, mask, val); - - mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL; - break; - case SND_SOC_DAIFMT_NB_IF: - val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED; - break; - case SND_SOC_DAIFMT_IB_NF: - val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL; - break; - case SND_SOC_DAIFMT_IB_IF: - val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED; - break; - default: - ret = -EINVAL; - break; - } + regmap_update_bits(sai->regmap, SAI_CKR, mask, val); - if (ret == 0) { - regmap_update_bits(sai->regmap, SAI_CKR, mask, val); - rockchip_sai_fmt_create(sai, fmt); - } - - if (clk_gates) - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, - clk_gates); + mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL; + break; + case SND_SOC_DAIFMT_NB_IF: + val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED; + break; + case SND_SOC_DAIFMT_IB_NF: + val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL; + break; + case SND_SOC_DAIFMT_IB_IF: + val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED; + break; + default: + ret = -EINVAL; + goto err_xfer_unlock; } + regmap_update_bits(sai->regmap, SAI_CKR, mask, val); + + rockchip_sai_fmt_create(sai, fmt); + +err_xfer_unlock: + if (clk_gates) + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, + clk_gates); + spin_unlock_irqrestore(&sai->xfer_lock, flags); +err_pm_put: pm_runtime_put(dai->dev); return ret; @@ -560,6 +564,7 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, unsigned int ch_per_lane, slot_width; unsigned int val, fscr, reg; unsigned int lanes, req_lanes; + unsigned long flags; int ret = 0; if (!rockchip_sai_stream_valid(substream, dai)) @@ -586,8 +591,8 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, dev_err(sai->dev, "not enough lanes (%d) for requested number of %s channels (%d)\n", lanes, reg == SAI_TXCR ? "playback" : "capture", params_channels(params)); - pm_runtime_put(sai->dev); - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; } else { lanes = req_lanes; } @@ -613,88 +618,84 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, val = SAI_XCR_VDW(32); break; default: - pm_runtime_put(sai->dev); - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; } val |= SAI_XCR_CSR(lanes); - scoped_guard(spinlock_irqsave, &sai->xfer_lock) { + spin_lock_irqsave(&sai->xfer_lock, flags); + + regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val); - regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val); + if (!sai->is_tdm) + regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(params_physical_width(params))); - if (!sai->is_tdm) - regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(params_physical_width(params))); + regmap_read(sai->regmap, reg, &val); - regmap_read(sai->regmap, reg, &val); + slot_width = SAI_XCR_SBW_V(val); + ch_per_lane = params_channels(params) / lanes; - slot_width = SAI_XCR_SBW_V(val); - ch_per_lane = params_channels(params) / lanes; + regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK, + SAI_XCR_SNB(ch_per_lane)); - regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK, - SAI_XCR_SNB(ch_per_lane)); + fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane); - fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane); + switch (sai->fpw) { + case FPW_ONE_BCLK_WIDTH: + fscr |= SAI_FSCR_FPW(1); + break; + case FPW_ONE_SLOT_WIDTH: + fscr |= SAI_FSCR_FPW(slot_width); + break; + case FPW_HALF_FRAME_WIDTH: + fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2); + break; + default: + dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw); + ret = -EINVAL; + goto err_xfer_unlock; + } - switch (sai->fpw) { - case FPW_ONE_BCLK_WIDTH: - fscr |= SAI_FSCR_FPW(1); - break; - case FPW_ONE_SLOT_WIDTH: - fscr |= SAI_FSCR_FPW(slot_width); - break; - case FPW_HALF_FRAME_WIDTH: - fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2); - break; - default: - dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw); + regmap_update_bits(sai->regmap, SAI_FSCR, + SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr); + + if (sai->is_master_mode) { + bclk_rate = sai->fw_ratio * slot_width * ch_per_lane * params_rate(params); + ret = clk_set_rate(sai->mclk, sai->mclk_rate); + if (ret) { + dev_err(sai->dev, "Failed to set mclk to %u: %pe\n", + sai->mclk_rate, ERR_PTR(ret)); + goto err_xfer_unlock; + } + + mclk_rate = clk_get_rate(sai->mclk); + if (mclk_rate < bclk_rate) { + dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n", + mclk_rate, bclk_rate); ret = -EINVAL; - break; + goto err_xfer_unlock; } - if (ret == 0) { - regmap_update_bits(sai->regmap, SAI_FSCR, - SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr); - - if (sai->is_master_mode) { - bclk_rate = sai->fw_ratio * slot_width * - ch_per_lane * params_rate(params); - ret = clk_set_rate(sai->mclk, sai->mclk_rate); - if (ret) - dev_err(sai->dev, "Failed to set mclk to %u: %pe\n", - sai->mclk_rate, ERR_PTR(ret)); - else { - mclk_rate = clk_get_rate(sai->mclk); - if (mclk_rate < bclk_rate) { - dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n", - mclk_rate, bclk_rate); - ret = -EINVAL; - } else { - - div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - mclk_req_rate = bclk_rate * div_bclk; - - if (mclk_rate < - mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX || - mclk_rate > - mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) { - dev_err(sai->dev, - "Mismatch mclk: %u, expected %u (+/- %dHz)\n", - mclk_rate, mclk_req_rate, - CLK_SHIFT_RATE_HZ_MAX); - ret = -EINVAL; - } else - regmap_update_bits(sai->regmap, - SAI_CKR, - SAI_CKR_MDIV_MASK, - SAI_CKR_MDIV(div_bclk)); - } - } - } + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); + mclk_req_rate = bclk_rate * div_bclk; + + if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX || + mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) { + dev_err(sai->dev, "Mismatch mclk: %u, expected %u (+/- %dHz)\n", + mclk_rate, mclk_req_rate, CLK_SHIFT_RATE_HZ_MAX); + ret = -EINVAL; + goto err_xfer_unlock; } + + regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK, + SAI_CKR_MDIV(div_bclk)); } +err_xfer_unlock: + spin_unlock_irqrestore(&sai->xfer_lock, flags); +err_pm_put: pm_runtime_put(sai->dev); return ret; @@ -704,6 +705,7 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); + unsigned long flags; if (!rockchip_sai_stream_valid(substream, dai)) return 0; @@ -724,12 +726,13 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream, * udelay falls short. */ udelay(20); - scoped_guard(spinlock_irqsave, &sai->xfer_lock) - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | - SAI_XFER_FSS_MASK, - SAI_XFER_CLK_EN | - SAI_XFER_FSS_EN); + spin_lock_irqsave(&sai->xfer_lock, flags); + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | + SAI_XFER_FSS_MASK, + SAI_XFER_CLK_EN | + SAI_XFER_FSS_EN); + spin_unlock_irqrestore(&sai->xfer_lock, flags); } rockchip_sai_fsync_lost_detect(sai, 1); @@ -912,6 +915,7 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai, int slots, int slot_width) { struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); + unsigned long flags; unsigned int clk_gates; int sw = slot_width; @@ -927,16 +931,16 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai, return -EINVAL; pm_runtime_get_sync(dai->dev); - scoped_guard(spinlock_irqsave, &sai->xfer_lock) { - rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); - regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(sw)); - regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(sw)); - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, - clk_gates); - } + spin_lock_irqsave(&sai->xfer_lock, flags); + rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); + regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(sw)); + regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(sw)); + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, + clk_gates); + spin_unlock_irqrestore(&sai->xfer_lock, flags); pm_runtime_put(dai->dev); return 0; From 0d9a72571e573a10edbfc2c172556c07aff5549b Mon Sep 17 00:00:00 2001 From: Sen Wang Date: Tue, 16 Jun 2026 18:33:22 -0500 Subject: [PATCH 0493/1058] ASoC: tlv320aic3x: restrict CLKDIV bypass Q values in dual-rate mode The datasheet documents that when the PLL is disabled and dual-rate mode is enabled, only Q values {4, 8, 9, 12, 16} are valid for the CLKDIV bypass path; all other Q values produce invalid bitclock output. The existing loop iterates Q from 2 to 17 without this restriction, causing silent audio failure when an out-of-spec Q is picked. Restrict the Q search to the allowed set in dual-rate mode. Fixes: 4f9c16ccfa26 ("[ALSA] soc - tlv320aic3x - revisit clock setup") Suggested-by: Mir Jeffres Signed-off-by: Sen Wang Link: https://patch.msgid.link/20260616233322.873081-1-sen@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index b12c1952823ba..b38393a8130ff 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1049,11 +1049,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + static const u8 dual_rate_q[] = {4, 8, 9, 12, 16}; struct snd_soc_component *component = dai->component; struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; u16 d, pll_d = 1; + bool dual_rate; int clk; int width = aic3x->slot_width; @@ -1079,14 +1081,25 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, /* Fsref can be 44100 or 48000 */ fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000; + dual_rate = params_rate(params) >= 64000; /* Try to find a value for Q which allows us to bypass the PLL and * generate CODEC_CLK directly. */ - for (pll_q = 2; pll_q < 18; pll_q++) - if (aic3x->sysclk / (128 * pll_q) == fsref) { - bypass_pll = 1; - break; + if (dual_rate) { + for (int i = 0; i < ARRAY_SIZE(dual_rate_q); i++) { + pll_q = dual_rate_q[i]; + if (aic3x->sysclk / (128 * pll_q) == fsref) { + bypass_pll = 1; + break; + } } + } else { + for (pll_q = 2; pll_q < 18; pll_q++) + if (aic3x->sysclk / (128 * pll_q) == fsref) { + bypass_pll = 1; + break; + } + } if (bypass_pll) { pll_q &= 0xf; @@ -1106,13 +1119,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, * right DAC to right channel input */ data = (LDAC2LCH | RDAC2RCH); data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000; - if (params_rate(params) >= 64000) + if (dual_rate) data |= DUAL_RATE_MODE; snd_soc_component_write(component, AIC3X_CODEC_DATAPATH_REG, data); /* codec sample rate select */ data = (fsref * 20) / params_rate(params); - if (params_rate(params) < 64000) + if (!dual_rate) data /= 2; data /= 5; data -= 2; From 40cccc2602baf2b6f67f11f34618a5b90fc990ea Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Mon, 15 Jun 2026 17:10:12 +0800 Subject: [PATCH 0494/1058] ASoC: rt5650: enhance spk protection function This patch adjusts several default settings to ensure the speaker protection function can be enabled safely. Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20260615091012.718168-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 6 ++---- sound/soc/codecs/rt5645.h | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 8a9af260e5f7f..e9819653b30d6 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -83,6 +83,8 @@ static const struct reg_sequence rt5650_init_list[] = { {RT5645_PWR_ANLG1, 0x02}, {RT5645_IL_CMD3, 0x6728}, {RT5645_PR_BASE + 0x3a, 0x0000}, + {RT5645_CLSD_OUT_CTRL1, 0x4059}, + {RT5645_GEN_CTRL3, 0x0200}, }; static const struct reg_default rt5645_reg[] = { @@ -1855,13 +1857,9 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w, RT5645_PWR_CLS_D_L, RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R | RT5645_PWR_CLS_D_L); - snd_soc_component_update_bits(component, RT5645_GEN_CTRL3, - RT5645_DET_CLK_MASK, RT5645_DET_CLK_MODE1); break; case SND_SOC_DAPM_PRE_PMD: - snd_soc_component_update_bits(component, RT5645_GEN_CTRL3, - RT5645_DET_CLK_MASK, RT5645_DET_CLK_DIS); snd_soc_component_write(component, RT5645_EQ_CTRL2, 0); snd_soc_component_update_bits(component, RT5645_PWR_DIG1, RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R | diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index bef74b29fd541..a5bfe9861b8ba 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h @@ -118,6 +118,7 @@ #define RT5645_A_JD_CTRL1 0x94 #define RT5645_VAD_CTRL4 0x9d #define RT5645_CLSD_OUT_CTRL 0xa0 +#define RT5645_CLSD_OUT_CTRL1 0xa1 /* Function - Digital */ #define RT5645_ADC_EQ_CTRL1 0xae #define RT5645_ADC_EQ_CTRL2 0xaf From daa668dece63cf0f20c021846dbace1e3d4e0740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvin=20=C5=A0ipraga?= Date: Wed, 17 Jun 2026 16:55:08 +0200 Subject: [PATCH 0495/1058] ASoC: audio-graph-card2: Drop warning for manually selected DAI formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes the DAI format must be specified in the audio-graph-card2 device tree, so emitting a warning can be misleading. Revert back to emitting no warning. A few examples where automatic format selection might not be applicable: - For DPCM, where the other side of the DAI link is not apparent, no proper selection can actually be made. This can lead to disagreeing formats. - Due to hardware peculiarities, some ostensibly supported formats might not work in practice. In either case, the only correct solution is for the sound card to set the format Link: https://lore.kernel.org/all/87ik7s36k2.wl-kuninori.morimoto.gx@renesas.com/ Signed-off-by: Alvin Šipraga Acked-by: Kuninori Morimoto Link: https://patch.msgid.link/20260617145508.327213-1-alvin@pqrs.dk Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 6894bb936cfd2..0202ed0ee78e8 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -778,18 +778,6 @@ static void graph_link_init(struct simple_util_priv *priv, graph_parse_daifmt(ports_cpu, &daifmt); graph_parse_daifmt(ports_codec, &daifmt); graph_parse_daifmt(lnk, &daifmt); - if (daifmt) { - struct device *dev = simple_priv_to_dev(priv); - - /* - * Recommend to use Auto Select by using .auto_selectable_formats. - * linux/sound/soc/renesas/rcar/core.c can be good sample for it. - * - * One note is that Audio Graph Card2 still keeps compatible to set - * DAI format via DT. - */ - dev_warn_once(dev, "use .auto_selectable_formats on each corresponding CPU/Codec driver"); - } graph_util_parse_link_direction(lnk, &playback_only, &capture_only); graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only); From b85b023309e58a86b9791d2b0b75ac6a330f3728 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 17 Jun 2026 16:47:53 +0200 Subject: [PATCH 0496/1058] ASoC: cs530x: Fix expected MCLK rates for CS5302/4/8 When this driver was first added, it accepted rates of 24.56 MHz and 22.572 MHz for the MCLK when PLL bypass is enabled. These rates seem to have no basis in the datasheets and were thus replaced with 45.1584 MHz and 49.152 MHz, respectively, in commit e7ab858390f2 ("ASoC: cs530x: Correct MCLK reference frequency values"). While the new rates are indeed correct for the CS4xxx ICs[0][1][2][3], they are incorrect for the CS530x ICs the driver was originally written to support as the MCLK frequencies are halved there[4][5][6]. Fix this by checking against the correct type-appropriate rates. While at it, drop the CS530X_SYSCLK_REF_* macros. They arguably confuse more than they help, especially as they are not applicable to the cs5302/4/8. [0]: https://statics.cirrus.com/pubs/proDatasheet/CS4282P_DS1318F1.pdf [1]: https://statics.cirrus.com/pubs/proDatasheet/CS4302P_DS1315F1.pdf [2]: https://statics.cirrus.com/pubs/proDatasheet/CS4304P_DS1316F1.pdf [3]: https://statics.cirrus.com/pubs/proDatasheet/CS4308P_DS1317F1.pdf [4]: https://statics.cirrus.com/pubs/proDatasheet/CS5302P_DS1312F1.pdf [5]: https://statics.cirrus.com/pubs/proDatasheet/CS5304P_DS1313F1.pdf [6]: https://statics.cirrus.com/pubs/proDatasheet/CS5308P_DS1314F1.pdf Fixes: 2884c29152c0 ("ASoC: cs530x: Support for cs530x ADCs") Signed-off-by: Ahmad Fatoum Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20260617-cs530x-mclk-v1-1-0215b5f1a0a4@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs530x.c | 29 ++++++++++++++++++++++++----- sound/soc/codecs/cs530x.h | 6 ------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c index 18b5ff75feec4..2c7e331359117 100644 --- a/sound/soc/codecs/cs530x.c +++ b/sound/soc/codecs/cs530x.c @@ -1093,6 +1093,29 @@ static int cs530x_component_probe(struct snd_soc_component *component) return 0; } +static bool cs530x_mclk_freq_is_valid(struct cs530x_priv *cs530x, + unsigned int freq) +{ + /* + * All these chips support 48 kHz- and 44.1 kHz-related sample rates, + * but they differ in what MCLK frequency is required for achieving + * the sample rate. + */ + switch (cs530x->devtype) { + case CS4282: + case CS4302: + case CS4304: + case CS4308: + return freq == 49152000 || freq == 45158400; + case CS5302: + case CS5304: + case CS5308: + return freq == 24576000 || freq == 22579200; + } + + return false; +} + static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { @@ -1101,11 +1124,7 @@ static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id, switch (source) { case CS530X_SYSCLK_SRC_MCLK: - switch (freq) { - case CS530X_SYSCLK_REF_45_1MHZ: - case CS530X_SYSCLK_REF_49_1MHZ: - break; - default: + if (!cs530x_mclk_freq_is_valid(cs530x, freq)) { dev_err(component->dev, "Invalid MCLK source rate %d\n", freq); return -EINVAL; } diff --git a/sound/soc/codecs/cs530x.h b/sound/soc/codecs/cs530x.h index 1e2f6a7a589c1..18aa4dfd0c860 100644 --- a/sound/soc/codecs/cs530x.h +++ b/sound/soc/codecs/cs530x.h @@ -200,12 +200,6 @@ /* IN_VOL_CTL5 and OUT_VOL_CTL5 */ #define CS530X_INOUT_VU BIT(0) -/* MCLK Reference Source Frequency */ -/* 41KHz related */ -#define CS530X_SYSCLK_REF_45_1MHZ 45158400 -/* 48KHz related */ -#define CS530X_SYSCLK_REF_49_1MHZ 49152000 - /* System Clock Source */ #define CS530X_SYSCLK_SRC_MCLK 0 #define CS530X_SYSCLK_SRC_PLL 1 From 4fe9cfd1789976284e5daf1bd8d930b110ac380f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 23 Jun 2026 11:18:10 +0100 Subject: [PATCH 0497/1058] soundwire: Move wait for initialisation helper to header As SoundWire devices tend to enumerate on the bus after probe, drivers frequently need to wait for the device to initialise from common driver code. The common system is to split drivers into a core module and then a module for each communication bus. These two facts tend to cause Kconfig issues, the issue tends to be when SOUNDWIRE=m and DRIVER_I2C=y, this usually selects DRIVER=y. The driver code then wants to call sdw_slave_wait_for_init(), but this results in calling a module function from built in code. A depends on SOUNDWIRE | !SOUNDWIRE could be added to the end driver but this seems slightly off as it adds a lot of counter intuitive depends. A simpler solution is to make sdw_slave_wait_for_init() a static inline function. As part of doing this add a check for the slave device being NULL acknowledging that this is likely called from code that is shared between control buses. It does require dropping the call to sdw_show_ping_status() but this can be added back in end drivers that used it originally. Currently this is causing rand config issues on RT5682 and will soon also cause similar problems on cs42l43. Acked-by: Vinod Koul Acked-by: Arnd Bergmann Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260623101814.24044-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/soundwire/bus.c | 28 -------------------------- include/linux/soundwire/sdw.h | 38 +++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index f38a0f7d0f27e..0490777fa4067 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1372,34 +1372,6 @@ int sdw_slave_get_current_bank(struct sdw_slave *slave) } EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank); -/** - * sdw_slave_wait_for_init - Wait for device initialisation - * @slave: Pointer to the SoundWire peripheral. - * @timeout_ms: Timeout in milliseconds. - * - * Wait for a peripheral device to enumerate and be initialised by the - * SoundWire core. - * - * Return: Zero on success, and a negative error code on failure. - */ -int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms) -{ - unsigned long time; - - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(timeout_ms)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete\n"); - sdw_show_ping_status(slave->bus, true); - return -ETIMEDOUT; - } - - slave->unattach_request = 0; - - return 0; -} -EXPORT_SYMBOL_GPL(sdw_slave_wait_for_init); - static int sdw_slave_set_frequency(struct sdw_slave *slave) { int scale_index; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index a46cbaec59491..b484784e2690d 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1093,8 +1094,6 @@ int sdw_slave_get_current_bank(struct sdw_slave *sdev); int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base); -int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms); - /* messaging and data APIs */ int sdw_read(struct sdw_slave *slave, u32 addr); int sdw_write(struct sdw_slave *slave, u32 addr, u8 value); @@ -1138,12 +1137,6 @@ static inline int sdw_slave_get_current_bank(struct sdw_slave *sdev) return -EINVAL; } -static inline int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms) -{ - WARN_ONCE(1, "SoundWire API is disabled"); - return -EINVAL; -} - /* messaging and data APIs */ static inline int sdw_read(struct sdw_slave *slave, u32 addr) { @@ -1207,4 +1200,33 @@ static inline int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u #endif /* CONFIG_SOUNDWIRE */ +/** + * sdw_slave_wait_for_init - Wait for device initialisation + * @slave: Pointer to the SoundWire peripheral. + * @timeout_ms: Timeout in milliseconds. + * + * Wait for a peripheral device to enumerate and be initialised by the + * SoundWire core. + * + * Return: Zero on success, and a negative error code on failure. + */ +static inline int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms) +{ + unsigned long time; + + if (!slave) + return 0; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(timeout_ms)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete\n"); + return -ETIMEDOUT; + } + + slave->unattach_request = 0; + + return 0; +} + #endif /* __SOUNDWIRE_H */ From a6be59319b531d4a369eccd68070f77246a2441c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 23 Jun 2026 11:18:11 +0100 Subject: [PATCH 0498/1058] ASoC: es9356: Add back local call to sdw_show_ping_status() As the core no longer calls this debug helper add it back to the drivers that originally called it. Acked-by: Arnd Bergmann Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260623101814.24044-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/es9356.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/es9356.c b/sound/soc/codecs/es9356.c index 670e918b56a46..8db81d5746240 100644 --- a/sound/soc/codecs/es9356.c +++ b/sound/soc/codecs/es9356.c @@ -1111,8 +1111,10 @@ static int es9356_sdca_dev_resume(struct device *dev) es9356->disable_irq = false; ret = sdw_slave_wait_for_init(slave, es9356_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(es9356->regmap, false); regcache_sync(es9356->regmap); From b926495b6aadcc47a75b1c0758d4360e22112fa2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 23 Jun 2026 11:18:12 +0100 Subject: [PATCH 0499/1058] ASoC: max98373: Add back local call to sdw_show_ping_status() As the core no longer calls this debug helper add it back to the drivers that originally called it. Acked-by: Arnd Bergmann Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260623101814.24044-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 6829fa07c9ecb..7a42052dc0516 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -272,8 +272,10 @@ static int max98373_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, MAX98373_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(max98373->regmap, false); regcache_sync(max98373->regmap); From f0b8d1b332246747fd629273181c7e6e7396b170 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 23 Jun 2026 11:18:13 +0100 Subject: [PATCH 0500/1058] ASoC: ti: Add back local call to sdw_show_ping_status() As the core no longer calls this debug helper add it back to the drivers that originally called it. Acked-by: Arnd Bergmann Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260623101814.24044-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/tac5xx2-sdw.c | 4 +++- sound/soc/codecs/tas2783-sdw.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tac5xx2-sdw.c b/sound/soc/codecs/tac5xx2-sdw.c index bb12cfb6da12b..ace06f5ab58c1 100644 --- a/sound/soc/codecs/tac5xx2-sdw.c +++ b/sound/soc/codecs/tac5xx2-sdw.c @@ -1445,8 +1445,10 @@ static s32 tac5xx2_sdca_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, TAC5XX2_PROBE_TIMEOUT_MS); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(tac_dev->regmap, false); regcache_mark_dirty(tac_dev->regmap); diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 7d70e7e3f24f4..1127ea59b5e4c 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -1083,8 +1083,10 @@ static s32 tas2783_sdca_dev_resume(struct device *dev) int ret; ret = sdw_slave_wait_for_init(slave, TAS2783_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(tas_dev->regmap, false); regcache_sync(tas_dev->regmap); From 1150a3b4750ba9a5261b48bc634c0f6ba6581cb1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 23 Jun 2026 11:18:14 +0100 Subject: [PATCH 0501/1058] ASoC: realtek: Add back local call to sdw_show_ping_status() As the core no longer calls this debug helper add it back to the drivers that originally called it. Acked-by: Arnd Bergmann Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260623101814.24044-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1017-sdca-sdw.c | 4 +++- sound/soc/codecs/rt1308-sdw.c | 4 +++- sound/soc/codecs/rt1316-sdw.c | 4 +++- sound/soc/codecs/rt5682-sdw.c | 4 +++- sound/soc/codecs/rt700-sdw.c | 4 +++- sound/soc/codecs/rt711-sdca-sdw.c | 4 +++- sound/soc/codecs/rt712-sdca-dmic.c | 4 +++- sound/soc/codecs/rt712-sdca-sdw.c | 4 +++- sound/soc/codecs/rt715-sdca-sdw.c | 4 +++- sound/soc/codecs/rt715-sdw.c | 4 +++- sound/soc/codecs/rt721-sdca-sdw.c | 4 +++- sound/soc/codecs/rt722-sdca-sdw.c | 4 +++- 12 files changed, 36 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c index d62e8a2536767..91d3d43cd9988 100644 --- a/sound/soc/codecs/rt1017-sdca-sdw.c +++ b/sound/soc/codecs/rt1017-sdca-sdw.c @@ -779,8 +779,10 @@ static int rt1017_sdca_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT1017_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt1017->regmap, false); regcache_sync(rt1017->regmap); diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 39e06a3a75609..60e5040b6dd9d 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -774,8 +774,10 @@ static int rt1308_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT1308_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt1308->regmap, false); regcache_sync_region(rt1308->regmap, 0xc000, 0xcfff); diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 1828fd9d5af6a..5e8eda6a5f7f8 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -751,8 +751,10 @@ static int rt1316_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT1316_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt1316->regmap, false); regcache_sync(rt1316->regmap); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index ec2a35a0cacde..dec8c2147d684 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -769,8 +769,10 @@ static int rt5682_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, RT5682_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt5682->sdw_regmap, false); regcache_cache_only(rt5682->regmap, false); diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 30fcca210f051..6bc636c86f427 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -528,8 +528,10 @@ static int rt700_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT700_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt700->regmap, false); regcache_sync_region(rt700->regmap, 0x3000, 0x8fff); diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index a8164fc3979ab..461315844ba99 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -454,8 +454,10 @@ static int rt711_sdca_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, RT711_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt711->regmap, false); regcache_sync(rt711->regmap); diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c index 4c5c2f5ba5edf..8b7d50a80ff98 100644 --- a/sound/soc/codecs/rt712-sdca-dmic.c +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -911,8 +911,10 @@ static int rt712_sdca_dmic_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt712->regmap, false); regcache_sync(rt712->regmap); diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c index 5817321804736..2787524c796e8 100644 --- a/sound/soc/codecs/rt712-sdca-sdw.c +++ b/sound/soc/codecs/rt712-sdca-sdw.c @@ -467,8 +467,10 @@ static int rt712_sdca_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt712->regmap, false); regcache_sync(rt712->regmap); diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 4b9815b5628db..fabd21bbbe5b9 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -230,8 +230,10 @@ static int rt715_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt715->regmap, false); regcache_sync_region(rt715->regmap, diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 7f83a8f1a06e9..a4a3945522e81 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -507,8 +507,10 @@ static int rt715_dev_resume(struct device *dev) return 0; ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt715->regmap, false); regcache_sync_region(rt715->regmap, 0x3000, 0x8fff); diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c index 58606209316a4..02df04a0ddad4 100644 --- a/sound/soc/codecs/rt721-sdca-sdw.c +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -505,8 +505,10 @@ static int rt721_sdca_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, RT721_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt721->regmap, false); regcache_sync(rt721->regmap); diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 0f76492ff915c..284900933ebf4 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -552,8 +552,10 @@ static int rt722_sdca_dev_resume(struct device *dev) } ret = sdw_slave_wait_for_init(slave, RT722_PROBE_TIMEOUT); - if (ret) + if (ret) { + sdw_show_ping_status(slave->bus, true); return ret; + } regcache_cache_only(rt722->regmap, false); regcache_sync(rt722->regmap); From 9b45ee2ca9d2ac222cfea85da82d5e806daf4d82 Mon Sep 17 00:00:00 2001 From: HyeongJun An Date: Tue, 23 Jun 2026 20:05:26 +0900 Subject: [PATCH 0502/1058] ASoC: SDCA: Validate written enum value in ge_put_enum_double() ge_put_enum_double() passes the user-supplied enumeration index item[0] to snd_soc_enum_item_to_val() without checking it against the number of items in the enum: ret = snd_soc_enum_item_to_val(e, item[0]); snd_soc_enum_item_to_val() indexes the heap-allocated e->values[] array with that index (e->values is set from a devm_kcalloc() of e->items entries), so a control write with an out-of-range item[0] reads past the end of the values buffer. The bounds check in snd_soc_dapm_put_enum_double() only runs afterwards, so it does not prevent the read here. Reject an out-of-range item before using it, matching the other enum put handlers. This issue was pointed out by the Sashiko AI review bot while reviewing a related enum-validation series: https://lore.kernel.org/all/20260609125735.CEB651F00893@smtp.kernel.org/ Fixes: 812ff1baa764 ("ASoC: SDCA: Limit values user can write to Selected Mode") Signed-off-by: HyeongJun An Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20260623110526.813217-1-sammiee5311@gmail.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_asoc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c index e76afa396b0ab..b4dedba719dc6 100644 --- a/sound/soc/sdca/sdca_asoc.c +++ b/sound/soc/sdca/sdca_asoc.c @@ -160,6 +160,9 @@ static int ge_put_enum_double(struct snd_kcontrol *kcontrol, unsigned int reg = e->reg; int ret; + if (item[0] >= e->items) + return -EINVAL; + reg &= ~SDW_SDCA_CTL_CSEL(0x3F); reg |= SDW_SDCA_CTL_CSEL(SDCA_CTL_GE_DETECTED_MODE); From a6976112e85ff764a29696233dc20bb1c4101189 Mon Sep 17 00:00:00 2001 From: Bartosz Juraszewski Date: Mon, 22 Jun 2026 20:27:33 +0200 Subject: [PATCH 0503/1058] ASoC: tas2783: Update loaded firmware names to linux-firmware 20260519 In linux-firmware commit from 2026-05-19 `2f90f4fe5c67f51a8410907a...` `ASoC: tas2783: Add Firmware files for tas2783A projects` by Baojun Xu 138 new firmware files for tas2783 were added, none of which are loaded by the kernel. Kernel expects files to be named with the following convention: "%04X-%1X-%1X.bin". However the added firmware files follow "-0x%1X.bin" naming instead with `0x` hex prefix, which fails to load resulting in following dmesg log: slave-tas2783 sdw:0:1:0102:0000:01:8: Direct firmware load for 1714-1-8.bin failed with error -2 slave-tas2783 sdw:0:1:0102:0000:01:8: Failed to read fw binary 1714-1-8.bin slave-tas2783 sdw:0:1:0102:0000:01:b: Direct firmware load for 1714-1-B.bin failed with error -2 slave-tas2783 sdw:0:1:0102:0000:01:b: Failed to read fw binary 1714-1-B.bin slave-tas2783 sdw:0:1:0102:0000:01:8: error playback without fw download slave-tas2783 sdw:0:1:0102:0000:01:8: ASoC error (-22): at snd_soc_dai_hw_params() on tas2783-codec This same commit removes all 22 symlinks from WHENCE, that used naming without the '0x' prefix to only 6 prevoiusly existing .bin files. This patch adds `0x` prefix explicitly to the generated firmware name allowing file to successfully load. In case prefixed firmware is missing due to out of date linux-firmware, we set the fallback flag and attempt to load firmware again based on the old file names. This prefix change results in functioning firmware loading on ASUS ProArt PX13 HN7306EAC, which uses 1714-1-0x8.bin and 1714-1-0xB.bin firmware files. Tested on top of 7.1 and next-20260619 with SND_SOC_AMD_ACP7X set to no. Signed-off-by: Bartosz Juraszewski Link: https://patch.msgid.link/20260622182733.23947-1-bjuraszewski@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2783-sdw.c | 73 +++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 1127ea59b5e4c..3d0b116544cc4 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -100,6 +100,8 @@ struct tas2783_prv { wait_queue_head_t fw_wait; bool fw_dl_task_done; bool fw_dl_success; + /* use fallback fw name */ + bool fw_use_fallback; }; static const struct reg_default tas2783_reg_default[] = { @@ -740,11 +742,19 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context) goto out; } + /* firmware binary not found*/ if (!fmw || !fmw->data) { - /* firmware binary not found*/ - dev_err(tas_dev->dev, - "Failed to read fw binary %s\n", - tas_dev->rca_binaryname); + if (!tas_dev->fw_use_fallback) { + tas_dev->fw_use_fallback = true; + dev_info(tas_dev->dev, + "Failed to read preferred fw binary: %s, attempting fallback binary load\n", + tas_dev->rca_binaryname); + } else { + dev_err(tas_dev->dev, + "Failed to read fallback fw binary %s\n", + tas_dev->rca_binaryname); + } + ret = -EINVAL; goto out; } @@ -1105,13 +1115,16 @@ static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t siz bool pci_found = false; #if IS_ENABLED(CONFIG_PCI) struct device *dev = &slave->dev; + struct tas2783_prv *tas_dev = dev_get_drvdata(&slave->dev); struct pci_dev *pci = NULL; + const char *fw_uid_prefix = tas_dev->fw_use_fallback ? "" : "0x"; for (; dev; dev = dev->parent) { if (dev->bus == &pci_bus_type) { pci = to_pci_dev(dev); - scnprintf(name, size, "%04X-%1X-%1X.bin", - pci->subsystem_device, bus->link_id, unique_id); + scnprintf(name, size, "%04X-%1X-%s%1X.bin", + pci->subsystem_device, bus->link_id, + fw_uid_prefix, unique_id); pci_found = true; break; } @@ -1123,28 +1136,15 @@ static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t siz bus->link_id, unique_id); } -static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) +static s32 tas_fw_load(struct tas2783_prv *tas_dev, struct sdw_slave *slave) { - struct tas2783_prv *tas_dev = dev_get_drvdata(dev); s32 ret; u8 unique_id = tas_dev->sdw_peripheral->id.unique_id; - if (tas_dev->hw_init) - return 0; - - tas_dev->fw_dl_task_done = false; - tas_dev->fw_dl_success = false; - - ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1); - if (ret) { - dev_err(dev, "sw reset failed, err=%d", ret); - return ret; - } - usleep_range(2000, 2200); - tas_generate_fw_name(slave, tas_dev->rca_binaryname, sizeof(tas_dev->rca_binaryname)); + tas_dev->fw_dl_task_done = false; ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, tas_dev->rca_binaryname, tas_dev->dev, GFP_KERNEL, tas_dev, tas2783_fw_ready); @@ -1159,8 +1159,35 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) msecs_to_jiffies(TIMEOUT_FW_DL_MS)); if (!ret) { dev_err(tas_dev->dev, "fw request, wait_event timeout\n"); - ret = -EAGAIN; - } else { + return -EAGAIN; + } + + return 0; +} + +static s32 tas_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct tas2783_prv *tas_dev = dev_get_drvdata(dev); + s32 ret; + + if (tas_dev->hw_init) + return 0; + + tas_dev->fw_dl_success = false; + + ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1); + if (ret) { + dev_err(dev, "sw reset failed, err=%d", ret); + return ret; + } + usleep_range(2000, 2200); + + tas_dev->fw_use_fallback = false; + ret = tas_fw_load(tas_dev, slave); + if (!ret && tas_dev->fw_use_fallback) + ret = tas_fw_load(tas_dev, slave); + + if (!ret) { if (tas_dev->sa_func_data) ret = sdca_regmap_write_init(dev, tas_dev->regmap, tas_dev->sa_func_data); From a96ac071f6e29c5afb6bd58f21e3843ba411da06 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Tue, 23 Jun 2026 18:25:14 +0800 Subject: [PATCH 0504/1058] ASoC: rt5575: Use __le32 for SPI burst write address The addr field in the SPI burst write buffer represents on-wire little-endian data. Define it as __le32 so that the assignment of cpu_to_le32() is type correct and avoids sparse endian warnings. Closes: https://lore.kernel.org/oe-kbuild-all/202606230139.rFZUVpCa-lkp@intel.com/ Fixes: 420739112e95 ("ASoC: rt5575: Add the codec driver for the ALC5575") Reported-by: kernel test robot Signed-off-by: Oder Chiou Link: https://patch.msgid.link/20260623102514.2422990-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5575-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5575-spi.c b/sound/soc/codecs/rt5575-spi.c index 9a349965435b6..d5b3a57c88666 100644 --- a/sound/soc/codecs/rt5575-spi.c +++ b/sound/soc/codecs/rt5575-spi.c @@ -17,7 +17,7 @@ struct rt5575_spi_burst_write { u8 cmd; - u32 addr; + __le32 addr; u8 data[RT5575_SPI_BUF_LEN]; u8 dummy; } __packed; From cda34fdb8f761c2ba6a1098dd57e993aca4b9e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Wed, 24 Jun 2026 10:37:07 +0200 Subject: [PATCH 0505/1058] ASoC: rockchip: rockchip_sai: #include explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently that header is only included via: -> -> which doesn't look reliable, still more in the presence of the comment: /* For the current users of sound/soc.h to avoid build issues */ in . Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Nicolas Frattaroli Link: https://patch.msgid.link/20260624083708.254517-2-u.kleine-koenig@baylibre.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_sai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index ed393e5034a49..585e89f61f0d9 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include From 5ab4416ccdeb38fa429d930b3042df389709ee83 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 23 Jun 2026 14:58:21 +0100 Subject: [PATCH 0506/1058] ASoC: soc-core: Don't fail if device_link could not be created If device_link_add() fails in snd_soc_bind_card() just skip that driver pair and carry on. This means that ASoC must now keep track of which components it was able to device_link to the card->dev. The new card_device_link member of struct snd_soc_component is non-NULL if a device_link exists. The intent of the device link is to ensure that the machine driver system-suspends before the component drivers, to prevent ASoC suspend attempting to reconfigure a driver that has already suspended. It isn't possible to create this device link if the machine driver is a parent of the component driver or already has a device_link in the opposite direction. In this case skip the link. A warn is placed in kernel log since this might indicate a genuine design problem with those two drivers (this can be downgraded to dbg in future when people are happy that all these special drivers correctly handle their reversed shutdown order). Fixes: 0f54ce994b23 ("ASoC: soc-core: Create device_link to ensure correct suspend order") Reported-by: Marek Szyprowski Closes: https://lore.kernel.org/linux-sound/61bd38e7-5eb9-4448-a93f-afa2ccbd1c9d@opensource.cirrus.com/T/#m496fe5a11b0a3649afd2e85da5e1cea82bb16d8a Tested-by: Marek Szyprowski Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20260623135821.4125543-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 4 ++++ sound/soc/soc-core.c | 35 +++++++++++++++-------------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 11bc9527653ff..aa423865dbe7c 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -10,6 +10,8 @@ #include +struct device_link; + /* * Component probe and remove ordering levels for components with runtime * dependencies. @@ -216,6 +218,8 @@ struct snd_soc_component { struct list_head card_aux_list; /* for auxiliary bound components */ struct list_head card_list; + struct device_link *card_device_link; + const struct snd_soc_component_driver *driver; struct list_head dai_list; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 86b6c752a56b7..7817beea5b3bc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1980,19 +1980,15 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) } } -static void snd_soc_remove_device_links(struct snd_soc_card *card, - struct snd_soc_component *stop_at) +static void snd_soc_remove_device_links(struct snd_soc_card *card) { struct snd_soc_component *component; for_each_card_components(card, component) { - if (card->dev == component->dev) - continue; - - device_link_remove(card->dev, component->dev); - - if (component == stop_at) - return; + if (component->card_device_link) { + device_link_del(component->card_device_link); + component->card_device_link = NULL; + } } } @@ -2001,7 +1997,7 @@ static void snd_soc_unbind_card(struct snd_soc_card *card) if (snd_soc_card_is_instantiated(card)) { card->instantiated = false; - snd_soc_remove_device_links(card, NULL); + snd_soc_remove_device_links(card); soc_cleanup_card_resources(card); } @@ -2012,7 +2008,6 @@ static int snd_soc_bind_card(struct snd_soc_card *card) struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); - struct snd_soc_component *last_devlinked_component = NULL; int ret; snd_soc_card_mutex_lock_root(card); @@ -2141,19 +2136,21 @@ static int snd_soc_bind_card(struct snd_soc_card *card) * Add device_link from card to component so that system_suspend * will be done in the correct order. The card must suspend first * to stop audio activity before the components suspend. + * + * If a driver pair already have a link in the opposite direction + * they must manage their own suspend order. */ for_each_card_components(card, component) { if (card->dev == component->dev) continue; - if (!device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) { - dev_warn(card->dev, "Failed to create device link to %s\n", + component->card_device_link = device_link_add(card->dev, + component->dev, + DL_FLAG_STATELESS); + if (!component->card_device_link) { + dev_warn(card->dev, "Could not create device link to %s\n", dev_name(component->dev)); - ret = -EINVAL; - goto probe_end; } - - last_devlinked_component = component; } ret = snd_soc_card_late_probe(card); @@ -2185,9 +2182,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) probe_end: if (ret < 0) { - if (last_devlinked_component) - snd_soc_remove_device_links(card, last_devlinked_component); - + snd_soc_remove_device_links(card); soc_cleanup_card_resources(card); } From 8084bfecdeea3433efb9abac58cce8c82edf06dc Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Thu, 25 Jun 2026 18:28:15 +0800 Subject: [PATCH 0507/1058] ASoC: tas2781: Update default register address to TAS2563 The previous TAS2781 address is overwritten during calibration, so switching to the TAS2563 address is required. Signed-off-by: Baojun Xu Link: https://patch.msgid.link/20260625102815.20043-1-baojun.xu@ti.com Signed-off-by: Mark Brown --- include/sound/tas2781.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index d45f805b5d18b..b763da6137699 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -59,9 +59,9 @@ #define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e) /* XM_340 */ -#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x63, 0x3c) +#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x02, 0x4c) /* XM_341 */ -#define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x63, 0x38) +#define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x02, 0x64) /* Volume control */ #define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0c) From 6542d1ac5b8567b25523f31692ce3f6c663d12d7 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 25 Jun 2026 12:28:11 +0000 Subject: [PATCH 0508/1058] ASoC: codecs: pcm512x: only print info once on no sclk If sclk is not provided the driver falls back to using bclk and prints an info message in the system log. Under normal operations the message is repeated many times: [ 17.929576] pcm512x 0-004c: No SCLK, using BCLK: -2 [ 17.949172] pcm512x 0-004c: No SCLK, using BCLK: -2 [ 17.953029] pcm512x 0-004c: No SCLK, using BCLK: -2 [ 17.965059] pcm512x 0-004c: No SCLK, using BCLK: -2 [ 82.592980] pcm512x 0-004c: No SCLK, using BCLK: -2 [ 82.866293] pcm512x 0-004c: No SCLK, using BCLK: -2 Switch from dev_info to dev_info_once to reduce log noise. Signed-off-by: Christian Hewitt Link: https://patch.msgid.link/20260625122811.4056274-1-christianshewitt@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index fdef98ce52f19..fe3b5011fa167 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -633,7 +633,7 @@ static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream, struct regmap *regmap = pcm512x->regmap; if (IS_ERR(pcm512x->sclk)) { - dev_info(dev, "No SCLK, using BCLK: %ld\n", + dev_info_once(dev, "No SCLK, using BCLK: %ld\n", PTR_ERR(pcm512x->sclk)); /* Disable reporting of missing SCLK as an error */ From f5a2fb8c900d0a082a9fa7a5789f8785abaaf509 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 25 Jun 2026 18:24:16 +0800 Subject: [PATCH 0509/1058] ASoC: fsl_asrc_dma: fix eDMA maxburst misalignment with channel count The back-end consumes data in units of the number of channels. When the maxburst value is not evenly divisible by the channel count, the DMA transfer length does not align with the FIFO frame boundary, causing wrong data to be copied and audible noise at the end of the stream. This is specific to eDMA: eDMA only responds to DMA requests from the back-end, whereas SDMA handles requests from both the front-end and the back-end and is not affected. For eDMA, when the back-end maxburst is not evenly divisible by the channel count, align it to the nearest valid boundary: - If maxburst >= channel count, override to the channel count so each transfer corresponds to exactly one audio frame. - If maxburst < channel count, override to 1 to avoid partial-frame transfers. Retain the original maxburst for SDMA or when it already aligns with the channel count. Fixes: c05f10f28ef6 ("ASoC: fsl_asrc: Add support for imx8qm & imx8qxp") Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20260625102416.424911-1-shengjiu.wang@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc_dma.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 5aa96af994c41..38f2b7c63133a 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -288,6 +288,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, config_be.dst_addr_width = buswidth; config_be.dst_maxburst = dma_params_be->maxburst; + /* + * For eDMA, the back-end may report a maxburst size that is not evenly + * divisible by the channel count. This causes the DMA transfer length + * to misalign with the FIFO boundary, resulting in wrong data and + * audible noise. Align maxburst to the nearest valid boundary: + * - If maxburst >= channel count, override to the channel count so + * each transfer equals exactly one audio frame. + * - If maxburst < channel count, override to 1 to avoid partial-frame + * transfers. + */ + if (asrc->use_edma && (dma_params_be->maxburst % params_channels(params))) { + if (dma_params_be->maxburst >= params_channels(params)) { + config_be.src_maxburst = params_channels(params); + config_be.dst_maxburst = params_channels(params); + } else { + config_be.src_maxburst = 1; + config_be.dst_maxburst = 1; + } + } + memset(&audio_config, 0, sizeof(audio_config)); config_be.peripheral_config = &audio_config; config_be.peripheral_size = sizeof(audio_config); From 87aad8b49aec042b3f8d46bfa303432218c8f7c0 Mon Sep 17 00:00:00 2001 From: Oleg Kucheryavenko Date: Thu, 25 Jun 2026 16:49:55 +0300 Subject: [PATCH 0510/1058] ALSA: hda/realtek: Update Acer Nitro ANV15-41 quirk to enable mute LED The laptop has a microphone mute LED on the F4 key, but it was not taken in mind when the previous quirk was added in commit 00e44a68efef50f65b12854b41f098b4d50f10be ("ALSA: hda/realtek: Add quirk for Acer Nitro ANV15-41"). Replace ALC2XX_FIXUP_HEADSET_MIC with ALC245_FIXUP_ACER_MICMUTE_LED, which enables the LED and chains the previous quirk for the headset microphone. Fixes: 00e44a68efef ("ALSA: hda/realtek: Add quirk for Acer Nitro ANV15-41") Signed-off-by: Oleg Kucheryavenko Link: https://patch.msgid.link/20260625134955.27465-1-oleg.kucheryavenko2018@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 71625394aa995..d9e2384fc0bad 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -6813,7 +6813,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x173a, "Acer Swift SFG14-73", ALC245_FIXUP_ACER_MICMUTE_LED), - SND_PCI_QUIRK(0x1025, 0x1758, "Acer Nitro ANV15-41", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x1758, "Acer Nitro ANV15-41", ALC245_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2), From 92646a94fa4aed1485870ac769c6d3e737d15cb1 Mon Sep 17 00:00:00 2001 From: Jiaming Zhang Date: Thu, 25 Jun 2026 21:49:33 +0800 Subject: [PATCH 0511/1058] ALSA: FCP: Fix NULL pointer dereference in interface lookup A malformed USB device can provide a vendor-specific interface without any endpoint descriptors. fcp_find_fc_interface() currently selects the first vendor-specific interface and reads endpoint 0 from it, without checking whether the interface actually has any endpoints. When bNumEndpoints is zero, no endpoint array is allocated for the parsed alternate setting, so get_endpoint(..., 0) yields an invalid endpoint descriptor pointer. Dereferencing it through usb_endpoint_num() then triggers a NULL pointer dereference. Skip vendor-specific interfaces that do not have any endpoints. Fixes: 46757a3e7d50 ("ALSA: FCP: Add Focusrite Control Protocol driver") Reported-by: Jiaming Zhang Closes: https://lore.kernel.org/lkml/CANypQFb1EHj0xX8bA1WxSOSK-5xca6ZNKzOQcp12=s=puY7VFw@mail.gmail.com/ Signed-off-by: Jiaming Zhang Link: https://patch.msgid.link/20260625134933.425785-1-r772577952@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/fcp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/fcp.c b/sound/usb/fcp.c index ea746bdb36ffc..6f5dcd35e1d4a 100644 --- a/sound/usb/fcp.c +++ b/sound/usb/fcp.c @@ -1083,6 +1083,8 @@ static int fcp_find_fc_interface(struct usb_mixer_interface *mixer) if (desc->bInterfaceClass != 255) continue; + if (desc->bNumEndpoints < 1) + continue; epd = get_endpoint(intf->altsetting, 0); private->bInterfaceNumber = desc->bInterfaceNumber; From 4472fe930326dde1ad15900317488ea653b68bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 17 Jun 2026 11:44:08 +0200 Subject: [PATCH 0512/1058] fbdev: vga16fb: Drop unused assignment of platform_device_id driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver explicitly sets the .driver_data member of struct platform_device_id to zero without relying on that value. Drop these unused assignments. While touching this array unify spacing and usage of commas and use named initializers for .name. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Helge Deller --- drivers/video/fbdev/vga16fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index 22085d3668e87..cdd6b8de0ceb2 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -1421,8 +1421,8 @@ static void vga16fb_remove(struct platform_device *dev) } static const struct platform_device_id vga16fb_driver_id_table[] = { - {"ega-framebuffer", 0}, - {"vga-framebuffer", 0}, + { .name = "ega-framebuffer" }, + { .name = "vga-framebuffer" }, { } }; MODULE_DEVICE_TABLE(platform, vga16fb_driver_id_table); From 6b569a15a53640cab865d7fc8d4e2662232aeb3b Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Sun, 21 Jun 2026 15:19:35 +0800 Subject: [PATCH 0513/1058] fbdev: pm2fb: unwind WC setup on probe failure Add arch_phys_wc_del() on error path to keep the write-combining setup balanced when later probe steps fail. Signed-off-by: Haoxiang Li Signed-off-by: Helge Deller --- drivers/video/fbdev/pm2fb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c index 412ff249b5c79..058075a34c5dc 100644 --- a/drivers/video/fbdev/pm2fb.c +++ b/drivers/video/fbdev/pm2fb.c @@ -1711,6 +1711,7 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) err_exit_both: kfree(info->pixmap.addr); err_exit_pixmap: + arch_phys_wc_del(default_par->wc_cookie); iounmap(info->screen_base); release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len); err_exit_mmio: From 44d1b9ee36b42df7a7a17f27781ad7fd4f161568 Mon Sep 17 00:00:00 2001 From: Mingyu Wang <25181214217@stu.xidian.edu.cn> Date: Fri, 26 Jun 2026 00:03:06 +0800 Subject: [PATCH 0514/1058] fbdev: fbcon: fix out-of-bounds read in err_out of fbcon_do_set_font() When fbcon_do_set_font() fails (e.g., due to a memory allocation failure inside vc_resize() under heavy memory pressure), it jumps to the `err_out` label to roll back the console state. However, the current rollback logic forgets to restore the `hi_font` state, leading to a severe state machine corruption. Earlier in the function, `set_vc_hi_font()` might be called to change `vc->vc_hi_font_mask` and mutate the screen buffer. If `vc_resize()` subsequently fails, the `err_out` path restores `vc_font.charcount` but entirely skips rolling back the `vc_hi_font_mask` and the screen buffer. This mismatch leaves the terminal in a desynchronized state. Because `vc_hi_font_mask` remains set, the VT subsystem will still accept character indices greater than 255 from userspace and write them to the screen buffer. Subsequent rendering calls (e.g., `fbcon_putcs()`) will then use these inflated indices to access the reverted, 256-character font array, leading to a deterministic out-of-bounds read and potential kernel memory disclosure. Fix this by adding the missing rollback logic for the `hi_font` mask and screen buffer in the error path. Fixes: a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed") Cc: stable@vger.kernel.org Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> Reviewed-by: Thomas Zimmermann Signed-off-by: Helge Deller --- drivers/video/fbdev/core/fbcon.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 9077d3b99357a..37beb93045af7 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2405,6 +2405,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, int resize, ret, old_width, old_height, old_charcount; font_data_t *old_fontdata = p->fontdata; const u8 *old_data = vc->vc_font.data; + unsigned short old_hi_font_mask = vc->vc_hi_font_mask; font_data_get(data); @@ -2451,6 +2452,12 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, vc->vc_font.height = old_height; vc->vc_font.charcount = old_charcount; + /* Restore the hi_font state and screen buffer */ + if (old_hi_font_mask && !vc->vc_hi_font_mask) + set_vc_hi_font(vc, true); + else if (!old_hi_font_mask && vc->vc_hi_font_mask) + set_vc_hi_font(vc, false); + font_data_put(data); return ret; From d2ff3412decdbb053957ace9dd8f9cd8981282b5 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Thu, 25 Jun 2026 11:01:02 +0800 Subject: [PATCH 0515/1058] fbdev: goldfishfb: fail pan display on base-update timeout goldfish_fb_pan_display() waits for the device to acknowledge the new framebuffer base, but it only logs a timeout and still reports success. The probe path also ignores the initial pan-display result before registering the framebuffer. Return -ETIMEDOUT when the base-update acknowledgment does not arrive, and propagate that error from the initial probe-time base update before the framebuffer is published. Signed-off-by: Pengpeng Hou Signed-off-by: Helge Deller --- drivers/video/fbdev/goldfishfb.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c index c9871281bc1da..e5d79886ea66b 100644 --- a/drivers/video/fbdev/goldfishfb.c +++ b/drivers/video/fbdev/goldfishfb.c @@ -138,10 +138,12 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var, writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset, fb->reg_base + FB_SET_BASE); spin_unlock_irqrestore(&fb->lock, irq_flags); - wait_event_timeout(fb->wait, - fb->base_update_count != base_update_count, HZ / 15); - if (fb->base_update_count == base_update_count) + if (!wait_event_timeout(fb->wait, + fb->base_update_count != base_update_count, + HZ / 15)) { pr_err("%s: timeout waiting for base update\n", __func__); + return -ETIMEDOUT; + } return 0; } @@ -251,7 +253,9 @@ static int goldfish_fb_probe(struct platform_device *pdev) goto err_request_irq_failed; writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE); - goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */ + ret = goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */ + if (ret) + goto err_pan_display_failed; ret = register_framebuffer(&fb->fb); if (ret) @@ -259,6 +263,7 @@ static int goldfish_fb_probe(struct platform_device *pdev) return 0; err_register_framebuffer_failed: +err_pan_display_failed: free_irq(fb->irq, fb); err_request_irq_failed: err_fb_set_var_failed: From ade09d6ee2760c6a6d77a78543a247a0a9b08ca4 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Wed, 24 Jun 2026 22:43:13 +0800 Subject: [PATCH 0516/1058] fbdev: viafb: return an error when DMA copy times out viafb_dma_copy_out_sg() logs a VIA DMA timeout when the DONE bit is not set after the completion wait and grace delay, but still returns success to the caller. Preserve the existing cleanup sequence and return -ETIMEDOUT when the DMA engine did not report completion. Signed-off-by: Pengpeng Hou Signed-off-by: Helge Deller --- drivers/video/fbdev/via/via-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c index a8d4a3e2c65ed..1632a669941ab 100644 --- a/drivers/video/fbdev/via/via-core.c +++ b/drivers/video/fbdev/via/via-core.c @@ -234,6 +234,7 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg) dma_addr_t descr_handle; unsigned long flags; int i; + int ret = 0; struct scatterlist *sgentry; dma_addr_t nextdesc; @@ -290,8 +291,10 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg) */ wait_for_completion_timeout(&viafb_dma_completion, 1); msleep(1); - if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0) + if ((viafb_mmio_read(VDMA_CSR0) & VDMA_C_DONE) == 0) { printk(KERN_ERR "VIA DMA timeout!\n"); + ret = -ETIMEDOUT; + } /* * Clean up and we're done. */ @@ -301,7 +304,7 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg) dma_free_coherent(&global_dev.pdev->dev, nsg*sizeof(struct viafb_vx855_dma_descr), descrpages, descr_handle); - return 0; + return ret; } EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg); #endif /* CONFIG_VIDEO_VIA_CAMERA */ From 1faf48c40cd2e3df931fb3f4f2c42734e2406589 Mon Sep 17 00:00:00 2001 From: Ian Bridges Date: Thu, 25 Jun 2026 23:50:48 -0500 Subject: [PATCH 0517/1058] fbdev: fix use-after-free in store_modes() store_modes() replaces a framebuffer's modelist with modes from userspace. On success it frees the old modelist with fb_destroy_modelist(). Two fields still point into that freed list. One pointer is fb_display[i].mode, the mode a console is using. fbcon_new_modelist() moves these pointers to the new list. It only does so for consoles still mapped to the framebuffer. An unmapped console is skipped and keeps its stale pointer. Unbinding fbcon, for example, sets con2fb_map[i] to -1 but leaves fb_display[i].mode set. An FBIOPUT_VSCREENINFO ioctl with FB_ACTIVATE_INV_MODE later reaches fbcon_mode_deleted(). That function reads the stale fb_display[i].mode through fb_mode_is_equal(). The read is a use-after-free. The other pointer is fb_info->mode, the current mode. It is set through the mode sysfs attribute. store_modes() does not update fb_info->mode, so it is left pointing into the freed list. show_mode(), the attribute's read handler, dereferences the stale fb_info->mode through mode_string(). The read is a use-after-free. Clear both pointers before freeing the list. Commit a1f305893074 ("fbcon: Set fb_display[i]->mode to NULL when the mode is released") added the helper fbcon_delete_modelist(). It clears every fb_display[i].mode that points into a given list. So far it is called only from the unregister path. Call it from store_modes() too, and set fb_info->mode to NULL. Reported-by: syzbot+81c7c6b52649fd07299d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=81c7c6b52649fd07299d Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/ajjoDhAi2y4ArSlz@dev/ Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ian Bridges Signed-off-by: Helge Deller --- drivers/video/fbdev/core/fbsysfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index d9743ef353552..ea196603c7a87 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c @@ -10,6 +10,7 @@ #include #include "fb_internal.h" +#include "fbcon.h" static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var) { @@ -108,8 +109,15 @@ static ssize_t store_modes(struct device *device, if (fb_new_modelist(fb_info)) { fb_destroy_modelist(&fb_info->modelist); list_splice(&old_list, &fb_info->modelist); - } else + } else { + /* + * fb_display[i].mode and fb_info->mode both point into the old + * list. Clear them before it is freed. + */ + fbcon_delete_modelist(&old_list); + fb_info->mode = NULL; fb_destroy_modelist(&old_list); + } unlock_fb_info(fb_info); console_unlock(); From 8f555f97d154bbe11df386f59363926787a9dfe8 Mon Sep 17 00:00:00 2001 From: Ian Bridges Date: Wed, 24 Jun 2026 16:11:36 -0500 Subject: [PATCH 0518/1058] fbcon: fix NULL pointer dereference for a console without vc_data fbcon_new_modelist() runs when a framebuffer's modelist changes. For each console mapped to it with fb_display[i].mode set, it reads vc_cons[i].d and passes the vc_num to fbcon_set_disp(). This assumes a console with a mode set has a vc_data, but it can be NULL. fbcon_set_disp() sets fb_display[i].mode before it checks vc_data, and fbcon_deinit() leaves the mode set after the vc_data is freed. fbcon_new_modelist() then dereferences the NULL vc_data. Keep fb_display[i].mode set only while the console has a vc_data. Check vc_data before setting the mode in fbcon_set_disp(), and clear the mode in fbcon_deinit(). The existing mode check in fbcon_new_modelist() then skips such consoles. Reported-by: syzbot+42525d636f430fd5d983@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=42525d636f430fd5d983 Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ian Bridges Signed-off-by: Helge Deller --- drivers/video/fbdev/core/fbcon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 37beb93045af7..9f5c4c101581d 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1273,6 +1273,7 @@ static void fbcon_deinit(struct vc_data *vc) int idx; fbcon_free_font(p); + p->mode = NULL; idx = con2fb_map[vc->vc_num]; if (idx == -1) @@ -1443,14 +1444,14 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, p = &fb_display[unit]; - if (var_to_display(p, var, info)) - return; - vc = vc_cons[unit].d; if (!vc) return; + if (var_to_display(p, var, info)) + return; + default_mode = vc->vc_display_fg; svc = *default_mode; t = &fb_display[svc->vc_num]; From 24f002b828369e37f71fc9eba7f0ab9b4796d558 Mon Sep 17 00:00:00 2001 From: Ian Bridges Date: Wed, 24 Jun 2026 23:13:12 -0500 Subject: [PATCH 0519/1058] fbdev: Fix fb_new_modelist to prevent null-ptr-deref in fb_videomode_to_var info->var, a framebuffer's current mode, is expected to have a matching entry in info->modelist. var_to_display() relies on this and treats a failed fb_match_mode() as "This should not happen". fb_set_var() keeps it true by adding the mode to the list on every change, and do_register_framebuffer() does the same at registration. store_modes() replaces the modelist from userspace. fb_new_modelist() validates the new modes but does not check that info->var still has a match. It relies on fbcon_new_modelist() to re-point consoles, but that only handles consoles mapped to the framebuffer. With fbcon unbound there are none, so info->var is left describing a mode that is no longer in the list. A later console takeover runs var_to_display(), where fb_match_mode() returns NULL and leaves fb_display[i].mode NULL. fbcon_switch() passes it to display_to_var(), and fb_videomode_to_var() dereferences the NULL mode. Keep the current mode in the list in fb_new_modelist(), the same way fb_set_var() does. Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ian Bridges Signed-off-by: Helge Deller --- drivers/video/fbdev/core/fbmem.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index e5221653ec2b9..2f1c56e5a7a23 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -767,6 +767,18 @@ int fb_new_modelist(struct fb_info *info) if (list_empty(&info->modelist)) return 1; + /* + * The new modelist may not contain the current mode (info->var), and + * fbcon_new_modelist() below only re-points consoles mapped to this + * framebuffer. Add the current mode here so info->var keeps a match + * even when fbcon is unbound. + */ + if (!fb_match_mode(&info->var, &info->modelist)) { + fb_var_to_videomode(&mode, &info->var); + if (fb_add_videomode(&mode, &info->modelist)) + return 1; + } + fbcon_new_modelist(info); return 0; From 52cced077098f41a30280c6b3f7694211ae6eaa8 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 4 Jun 2026 10:56:31 +0100 Subject: [PATCH 0520/1058] pwm: rzg2l-gpt: Fix period_ticks type from u32 to u64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit period_ticks is used to store PWM period values that can exceed the 32-bit range, so change its type from u32 to u64 to prevent overflow. Cc: stable@kernel.org Fixes: 061f087f5d0b ("pwm: Add support for RZ/G2L GPT") Signed-off-by: Biju Das Link: https://patch.msgid.link/20260604095647.108654-2-biju.das.jz@bp.renesas.com Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-rzg2l-gpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-rzg2l-gpt.c b/drivers/pwm/pwm-rzg2l-gpt.c index 4856af080e8e9..c9dfa59bc1ead 100644 --- a/drivers/pwm/pwm-rzg2l-gpt.c +++ b/drivers/pwm/pwm-rzg2l-gpt.c @@ -81,7 +81,7 @@ struct rzg2l_gpt_chip { void __iomem *mmio; struct mutex lock; /* lock to protect shared channel resources */ unsigned long rate_khz; - u32 period_ticks[RZG2L_MAX_HW_CHANNELS]; + u64 period_ticks[RZG2L_MAX_HW_CHANNELS]; u32 channel_request_count[RZG2L_MAX_HW_CHANNELS]; u32 channel_enable_count[RZG2L_MAX_HW_CHANNELS]; }; From a60c3430a69d78e8ef04c88121dd28da5cd9f32e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 4 Jun 2026 10:56:34 +0100 Subject: [PATCH 0521/1058] pwm: rzg2l-gpt: Add missing newlines to dev_err_probe() messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_err_probe() internally calls dev_err() which uses pr_fmt() and printk(). Kernel log messages should end with a newline character to ensure proper log formatting. Add missing '\n' at the end of the error strings in rzg2l_gpt_probe(). Signed-off-by: Biju Das Link: https://patch.msgid.link/20260604095647.108654-5-biju.das.jz@bp.renesas.com Fixes: 061f087f5d0b ("pwm: Add support for RZ/G2L GPT") Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-rzg2l-gpt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-rzg2l-gpt.c b/drivers/pwm/pwm-rzg2l-gpt.c index c9dfa59bc1ead..dfa1d11a48a82 100644 --- a/drivers/pwm/pwm-rzg2l-gpt.c +++ b/drivers/pwm/pwm-rzg2l-gpt.c @@ -408,14 +408,14 @@ static int rzg2l_gpt_probe(struct platform_device *pdev) rate = clk_get_rate(clk); if (!rate) - return dev_err_probe(dev, -EINVAL, "The gpt clk rate is 0"); + return dev_err_probe(dev, -EINVAL, "The gpt clk rate is 0\n"); /* * Refuse clk rates > 1 GHz to prevent overflow later for computing * period and duty cycle. */ if (rate > NSEC_PER_SEC) - return dev_err_probe(dev, -EINVAL, "The gpt clk rate is > 1GHz"); + return dev_err_probe(dev, -EINVAL, "The gpt clk rate is > 1GHz\n"); /* * Rate is in MHz and is always integer for peripheral clk @@ -424,7 +424,7 @@ static int rzg2l_gpt_probe(struct platform_device *pdev) */ rzg2l_gpt->rate_khz = rate / KILO; if (rzg2l_gpt->rate_khz * KILO != rate) - return dev_err_probe(dev, -EINVAL, "Rate is not multiple of 1000"); + return dev_err_probe(dev, -EINVAL, "Rate is not multiple of 1000\n"); mutex_init(&rzg2l_gpt->lock); From 0f46414087e54d8ab771f30a10d86d9ff4e68f06 Mon Sep 17 00:00:00 2001 From: Bryam Vargas Date: Sun, 14 Jun 2026 00:36:11 -0500 Subject: [PATCH 0522/1058] Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count rmi_f3a_initialize() takes the GPIO count from the device query register (f3a->gpio_count = buf & RMI_F3A_GPIO_COUNT, range 0..127). rmi_f3a_map_gpios() then allocates gpio_key_map with min(gpio_count, TRACKSTICK_RANGE_END) == at most 6 entries, but rmi_f3a_attention() iterates the full gpio_count and dereferences gpio_key_map[i], and input->keycodemax is set to the full gpio_count while input->keycode points at the 6-entry allocation. A device that reports gpio_count > 6 therefore causes an out-of-bounds read of gpio_key_map[] on every attention interrupt, and out-of-bounds accesses through the input core's default keymap ioctls: EVIOCGKEYCODE reads past the buffer (leaking adjacent slab memory to user space) and EVIOCSKEYCODE writes a caller-controlled value past it, for any process able to open the evdev node, since input_default_getkeycode() and input_default_setkeycode() only bound the index against keycodemax. Size the keymap for the full gpio_count. The mapping loop is unchanged: it still assigns only the first min(gpio_count, TRACKSTICK_RANGE_END) entries; the remaining slots stay KEY_RESERVED (devm_kcalloc zero-fills) and are skipped when reporting. Fixes: 9e4c596bfd00 ("Input: synaptics-rmi4 - add support for F3A") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas Link: https://patch.msgid.link/20260614-b4-disp-818d6bda-v1-1-cf39a3615085@proton.me Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f3a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_f3a.c b/drivers/input/rmi4/rmi_f3a.c index 0e8baed84dbb5..a0777644eef07 100644 --- a/drivers/input/rmi4/rmi_f3a.c +++ b/drivers/input/rmi4/rmi_f3a.c @@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a, int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END); f3a->gpio_key_map = devm_kcalloc(&fn->dev, - button_count, + f3a->gpio_count, sizeof(f3a->gpio_key_map[0]), GFP_KERNEL); if (!f3a->gpio_key_map) { From 0e364fd8bf440336ecc346cd9cca028caa543738 Mon Sep 17 00:00:00 2001 From: Bryam Vargas Date: Sun, 14 Jun 2026 00:36:12 -0500 Subject: [PATCH 0523/1058] Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count rmi_f30_map_gpios() allocates gpioled_key_map with min(gpioled_count, TRACKSTICK_RANGE_END) == at most 6 entries, but rmi_f30_attention() iterates the full f30->gpioled_count (device query register, range 0..31) and dereferences gpioled_key_map[i], and input->keycodemax is set to the full gpioled_count while input->keycode points at the 6-entry allocation. A device that reports gpioled_count > 6 with GPIO support enabled therefore causes an out-of-bounds read on the attention interrupt and out-of-bounds read/write through the EVIOCGKEYCODE/EVIOCSKEYCODE ioctls, which bound the index only against keycodemax. This is the same defect as the F3A handler, which was copied from F30. Size the keymap for the full gpioled_count; the mapping loop still assigns only the first min(gpioled_count, TRACKSTICK_RANGE_END) entries. Fixes: 3e64fcbdbd10 ("Input: synaptics-rmi4 - limit the range of what GPIOs are buttons") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas Link: https://patch.msgid.link/20260614-b4-disp-818d6bda-v1-2-cf39a3615085@proton.me Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c index 35045f161dc2f..b2155c8e20e75 100644 --- a/drivers/input/rmi4/rmi_f30.c +++ b/drivers/input/rmi4/rmi_f30.c @@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn, int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END); f30->gpioled_key_map = devm_kcalloc(&fn->dev, - button_count, + f30->gpioled_count, sizeof(f30->gpioled_key_map[0]), GFP_KERNEL); if (!f30->gpioled_key_map) { From 781a474595d83727667bd4bacb7e5af60866e3d6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 26 Jun 2026 17:42:10 -0700 Subject: [PATCH 0524/1058] Revert "Input: rmi4 - fix register descriptor address calculation" The register descriptor presence register is a packet register, which means its bytes share a single RMI address. It does not occupy consecutive addresses, and the register structure that follows it is located at the next RMI address (presence_address + 1), not (presence_address + presence_size). Revert the incorrect address calculation introduced in commit a98518e72439. Reported-by: "Barry K. Nathan" Tested-by: "Barry K. Nathan" Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index 49a59da6a8411..a28eef1b765e5 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -643,7 +643,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, ret = rmi_read_block(d, addr, buf, size_presence_reg); if (ret) return ret; - addr += size_presence_reg; + ++addr; if (buf[0] == 0) { if (size_presence_reg < 3) From 02df8a7b69230a64c56fbdc2b64027a82451c195 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 26 Jun 2026 16:33:21 -0700 Subject: [PATCH 0525/1058] Input: rmi4 - tolerate short register descriptor structure Some touchpads (e.g. ThinkPad T14 Gen 1) have buggy firmware that reports a register descriptor structure size that is too small for the number of registers it claims to have in the presence map. The remaining bytes in the structure are 0, which with the new strict bounds checking causes the parser to fail with -EIO, aborting the device probe. Tolerate such short reads by dropping the remaining (unparseable or 0-size) registers from the list instead of failing the probe, preventing the driver from trying to use them. Fixes: 0adb483fbf2d ("Input: rmi4 - refactor register descriptor parsing") Reported-by: Barry K. Nathan Tested-by: Barry K. Nathan Cc: stable@vger.kernel.org Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_driver.c | 37 ++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index a28eef1b765e5..5d49a9021c7d0 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -616,8 +616,8 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, unsigned int presence_offset; unsigned int map_offset; unsigned int offset; + unsigned int num_registers; unsigned int reg; - int i; int b; int ret; @@ -657,7 +657,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, memset(presence_map, 0, sizeof(presence_map)); map_offset = 0; - for (i = presence_offset; i < size_presence_reg; i++) { + for (int i = presence_offset; i < size_presence_reg; i++) { for (b = 0; b < 8; b++) { if (buf[i] & BIT(b)) { if (map_offset >= RMI_REG_DESC_PRESENCE_BITS) @@ -697,28 +697,41 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, if (ret) return ret; - reg = find_first_bit(presence_map, RMI_REG_DESC_PRESENCE_BITS); offset = 0; - for (i = 0; i < rdesc->num_registers; i++) { - struct rmi_register_desc_item *item = &rdesc->registers[i]; + num_registers = 0; + for_each_set_bit(reg, presence_map, RMI_REG_DESC_PRESENCE_BITS) { + struct rmi_register_desc_item *item = &rdesc->registers[num_registers]; int item_size; + if (offset >= rdesc->struct_size) + break; + item_size = rmi_parse_register_desc_item(item, &struct_buf[offset], rdesc->struct_size - offset); - if (item_size < 0) - return item_size; + if (item_size < 0) { + dev_warn(&d->dev, + "%s: Failed to parse register %d descriptor, ignoring it\n", + __func__, reg); + break; + } item->reg = reg; offset += item_size; - rmi_dbg(RMI_DEBUG_CORE, &d->dev, - "%s: reg: %d reg size: %u subpackets: %d\n", __func__, - item->reg, item->reg_size, item->num_subpackets); + if (item->reg_size == 0) { + dev_warn(&d->dev, + "%s: Register %d has 0 size, ignoring it\n", + __func__, item->reg); + } else { + rmi_dbg(RMI_DEBUG_CORE, &d->dev, + "%s: reg: %d reg size: %u subpackets: %d\n", __func__, + item->reg, item->reg_size, item->num_subpackets); - reg = find_next_bit(presence_map, - RMI_REG_DESC_PRESENCE_BITS, reg + 1); + num_registers++; + } } + rdesc->num_registers = num_registers; return 0; } From 13517ac9d4698a898a16d1f7630387fb441232fa Mon Sep 17 00:00:00 2001 From: Xu Rao Date: Wed, 24 Jun 2026 17:47:39 +0800 Subject: [PATCH 0526/1058] Input: gscps2 - advance receive buffer write index Commit 44f920069911 ("Input: gscps2 - use guard notation when acquiring spinlock") moved the receive loop into gscps2_read_data() and gscps2_report_data(). While moving the code, it preserved the writes to buffer[ps2port->append], but omitted the following producer index update from the original loop: ps2port->append = (ps2port->append + 1) & BUFFER_SIZE; As a result, append never advances. Since gscps2_report_data() only reports bytes while act != append, the receive buffer always appears empty and no keyboard or mouse data reaches the serio core. Restore the omitted index update. Fixes: 44f920069911 ("Input: gscps2 - use guard notation when acquiring spinlock") Cc: stable@vger.kernel.org # 6.13+ Signed-off-by: Xu Rao Link: https://patch.msgid.link/460B5655BA580C60+20260624094739.850306-1-raoxu@uniontech.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/gscps2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 22b2f57fd91f5..bf9b993f57330 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -219,6 +219,7 @@ static void gscps2_read_data(struct gscps2port *ps2port) ps2port->buffer[ps2port->append].str = status; ps2port->buffer[ps2port->append].data = gscps2_readb_input(ps2port->addr); + ps2port->append = (ps2port->append + 1) & BUFFER_SIZE; } while (true); } From 163294571323a5a22763ab1346a73a8da2d1eb0f Mon Sep 17 00:00:00 2001 From: Alok Tiwari Date: Sun, 8 Feb 2026 08:49:00 -0800 Subject: [PATCH 0527/1058] ntb_hw_amd: Fix incorrect debug message in link disable path amd_ntb_link_disable() prints "Enabling Link" which is misleading. Update the message to reflect that the link is being disabled. Signed-off-by: Alok Tiwari Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/amd/ntb_hw_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index 1a163596ddf54..df9150669ad3a 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -376,7 +376,7 @@ static int amd_ntb_link_disable(struct ntb_dev *ntb) if (ndev->ntb.topo == NTB_TOPO_SEC) return -EINVAL; - dev_dbg(&ntb->pdev->dev, "Enabling Link.\n"); + dev_dbg(&ntb->pdev->dev, "Disabling Link.\n"); return 0; } From 814af522523944124e3abb1f1d1fb55862505410 Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Wed, 4 Mar 2026 11:05:27 +0900 Subject: [PATCH 0528/1058] NTB: epf: Avoid pci_iounmap() with offset when PEER_SPAD and CONFIG share BAR When BAR_PEER_SPAD and BAR_CONFIG share one PCI BAR, the module teardown path ends up calling pci_iounmap() on the same iomem with some offset, which is unnecessary and triggers a kernel warning like the following: Trying to vunmap() nonexistent vm area (0000000069a5ffe8) WARNING: mm/vmalloc.c:3470 at vunmap+0x58/0x68, CPU#5: modprobe/2937 [...] Call trace: vunmap+0x58/0x68 (P) iounmap+0x34/0x48 pci_iounmap+0x2c/0x40 ntb_epf_pci_remove+0x44/0x80 [ntb_hw_epf] pci_device_remove+0x48/0xf8 device_remove+0x50/0x88 device_release_driver_internal+0x1c8/0x228 driver_detach+0x50/0xb0 bus_remove_driver+0x74/0x100 driver_unregister+0x34/0x68 pci_unregister_driver+0x34/0xa0 ntb_epf_pci_driver_exit+0x14/0xfe0 [ntb_hw_epf] [...] Fix it by unmapping only when PEER_SPAD and CONFIG use difference bars. Cc: stable@vger.kernel.org Fixes: e75d5ae8ab88 ("NTB: epf: Allow more flexibility in the memory BAR map method") Reviewed-by: Frank Li Signed-off-by: Koichiro Den Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/epf/ntb_hw_epf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c index af57554728429..c47607d4f8a7f 100644 --- a/drivers/ntb/hw/epf/ntb_hw_epf.c +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c @@ -729,7 +729,8 @@ static void ntb_epf_deinit_pci(struct ntb_epf_dev *ndev) struct pci_dev *pdev = ndev->ntb.pdev; pci_iounmap(pdev, ndev->ctrl_reg); - pci_iounmap(pdev, ndev->peer_spad_reg); + if (ndev->barno_map[BAR_PEER_SPAD] != ndev->barno_map[BAR_CONFIG]) + pci_iounmap(pdev, ndev->peer_spad_reg); pci_iounmap(pdev, ndev->db_reg); pci_release_regions(pdev); From aa0f804a4f29f75bdb6e41939a06100297d19832 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Mar 2026 22:14:15 -0700 Subject: [PATCH 0529/1058] NTB: fix kernel-doc warnings in ntb.h Correct a function name and function parameter name to avoid kernel-doc warnings: Warning: include/linux/ntb.h:575 expecting prototype for ntb_default_port_count(). Prototype was for ntb_default_peer_port_count() instead Warning: include/linux/ntb.h:590 function parameter 'pidx' not described in 'ntb_default_peer_port_number' Signed-off-by: Randy Dunlap Acked-by: Dave Jiang Signed-off-by: Jon Mason --- include/linux/ntb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ntb.h b/include/linux/ntb.h index 879c3e89e026f..ae72caa038597 100644 --- a/include/linux/ntb.h +++ b/include/linux/ntb.h @@ -567,7 +567,7 @@ void ntb_msg_event(struct ntb_dev *ntb); int ntb_default_port_number(struct ntb_dev *ntb); /** - * ntb_default_port_count() - get the default number of peer device ports + * ntb_default_peer_port_count() - get the default number of peer device ports * @ntb: NTB device context. * * By default hardware driver supports just one peer device. @@ -582,7 +582,7 @@ int ntb_default_peer_port_count(struct ntb_dev *ntb); /** * ntb_default_peer_port_number() - get the default peer port by given index * @ntb: NTB device context. - * @idx: Peer port index (should not differ from zero). + * @pidx: Peer port index (should not differ from zero). * * By default hardware driver supports just one peer device, so this method * shall return the corresponding value from enum ntb_default_port. From 7b92541d21f300d6b355d43a2c211c12cbbcb2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Thu, 7 May 2026 09:41:01 +0200 Subject: [PATCH 0530/1058] ntb: amd: Use named initializer for pci_device_id::driver_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current list initialisation depends on the well hidden two zeros in the PCI_VDEVICE macro. Instead use a named initialisation that is more robust and easier to understand. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Dave Jiang Signed-off-by: Jon Mason --- drivers/ntb/hw/amd/ntb_hw_amd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index df9150669ad3a..36bee0d8ac6cd 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -1328,15 +1328,15 @@ static const struct ntb_dev_data dev_data[] = { }; static const struct pci_device_id amd_ntb_pci_tbl[] = { - { PCI_VDEVICE(AMD, 0x145b), (kernel_ulong_t)&dev_data[0] }, - { PCI_VDEVICE(AMD, 0x148b), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x17d4), (kernel_ulong_t)&dev_data[1] }, - { PCI_VDEVICE(AMD, 0x17d7), (kernel_ulong_t)&dev_data[2] }, - { PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] }, - { 0, } + { PCI_VDEVICE(AMD, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] }, + { PCI_VDEVICE(AMD, 0x148b), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x14c0), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x14c3), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x155a), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x17d4), .driver_data = (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x17d7), .driver_data = (kernel_ulong_t)&dev_data[2] }, + { PCI_VDEVICE(HYGON, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] }, + { } }; MODULE_DEVICE_TABLE(pci, amd_ntb_pci_tbl); From c8aa1c84342ff8168cb18487d213243840f58ec1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 Jun 2026 12:01:31 -0700 Subject: [PATCH 0531/1058] Linux 7.2-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 12fd3d2d47b58..b9c5792c79e01 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 7 -PATCHLEVEL = 1 +PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Baby Opossum Posse # *DOCUMENTATION* From 42c2f5ba420018099ff6e96616695c1f3da0a368 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:23 +0530 Subject: [PATCH 0532/1058] FROMLIST: arm64: dts: qcom: lemans: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "bootloader" will cause device to reboot and stop in the bootloader's fastboot mode. "edl" will cause device to reboot into "emergency download mode", which permits loading images via the Firehose protocol. Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-10-46e085bca4cc@oss.qualcomm.com Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/lemans.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb..f37512eefdb8e 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -635,6 +635,11 @@ #power-domain-cells = <0>; domain-idle-states = <&cluster_sleep_apss_rsc_pc>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { From 3d35b8c34b4739368861b43e37b09756166d7807 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 12 Nov 2025 12:08:26 +0530 Subject: [PATCH 0533/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Enable Bluetooth support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a WCN6855 WiFi/Bluetooth module on an M.2 card. To make Bluetooth work, we need to define the necessary device tree nodes, including UART configuration and power supplies. Since there is no standard M.2 binding in the device tree at present, the PMU is described using dedicated PMU nodes to represent the internal regulators required by the module. The module provides a 3.3V supply, which originates from the main board’s 12V rail. To represent this power hierarchy in the device tree, add a fixed 12V regulator node as the DC-IN source and link it to the 3.3V regulator node. Link: https://lore.kernel.org/all/20251112071147.1450258-2-wei.deng@oss.qualcomm.com/ Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 34dfc8d22b6a5..34ebbe1eac0a0 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -21,6 +21,7 @@ ethernet0 = ðernet0; mmc1 = &sdhc; serial0 = &uart10; + serial1 = &uart17; serial2 = &uart0; }; @@ -178,6 +179,17 @@ regulator-max-microvolt = <2950000>; }; + vreg_dcin_12v: regulator-dcin-12v { + compatible = "regulator-fixed"; + + regulator-name = "VREG_DCIN_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + + regulator-boot-on; + regulator-always-on; + }; + vreg_sdc: regulator-vreg-sdc { compatible = "regulator-gpio"; @@ -191,6 +203,75 @@ startup-delay-us = <100>; }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + vin-supply = <&vreg_dcin_12v>; + + regulator-boot-on; + }; + + wcn6855-pmu { + compatible = "qcom,wcn6855-pmu"; + + vddio-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddpmu-supply = <&vreg_wcn_3p3>; + vddpmumx-supply = <&vreg_wcn_3p3>; + vddpmucx-supply = <&vreg_wcn_3p3>; + vddrfa0p95-supply = <&vreg_wcn_3p3>; + vddrfa1p3-supply = <&vreg_wcn_3p3>; + vddrfa1p9-supply = <&vreg_wcn_3p3>; + vddpcielp3-supply = <&vreg_wcn_3p3>; + vddpcielp9-supply = <&vreg_wcn_3p3>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 { + regulator-name = "vreg_pmu_rfa_cmn"; + }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + }; + + vreg_pmu_wlcx_0p8: ldo2 { + regulator-name = "vreg_pmu_wlcx_0p8"; + }; + + vreg_pmu_wlmx_0p85: ldo3 { + regulator-name = "vreg_pmu_wlmx_0p85"; + }; + + vreg_pmu_btcmx_0p85: ldo4 { + regulator-name = "vreg_pmu_btcmx_0p85"; + }; + + vreg_pmu_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -970,6 +1051,24 @@ status = "okay"; }; +&uart17 { + status = "okay"; + + bluetooth: bluetooth { + compatible = "qcom,wcn6855-bt"; + max-speed = <3200000>; + + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + }; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; vcc-supply = <&vreg_l8a>; From 0f65e49a71e48eaad4b2c994b224e5a31fc76005 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 24 Nov 2025 14:55:17 +0530 Subject: [PATCH 0534/1058] FROMLIST: dt-bindings: phy: describe additional regulator for Qualcomm SGMII PHY Describe the additional vdda-0p9-supply for the Qualcomm SGMII PHY. Link: https://lore.kernel.org/r/20251124-sgmiieth_serdes_regulator-v1-1-73ae8f9cbe2a@oss.qualcomm.com Signed-off-by: Mohd Ayaan Anwar --- .../devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml index 90fc8c039219c..0a1330b9118d6 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml @@ -36,6 +36,10 @@ properties: description: Phandle to a regulator that provides power to the PHY. + vdda-0p9-supply: + description: + Phandle to a 0.9V regulator supply to the PHY. + "#phy-cells": const: 0 From f9412401f260e92d1c7a10c83467a4e4b574321f Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 24 Nov 2025 14:55:18 +0530 Subject: [PATCH 0535/1058] FROMLIST: arm64: dts: qcom: lemans-evk: add additional SerDes PHY regulator Add the additional 0.9V regulator for the Qualcomm SerDes PHY. Fixes: 71ee90ed1756 ("arm64: dts: qcom: lemans-evk: Enable 2.5G Ethernet interface") Link: https://lore.kernel.org/r/20251124-sgmiieth_serdes_regulator-v1-2-73ae8f9cbe2a@oss.qualcomm.com Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 34ebbe1eac0a0..ae6976f34bd77 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -914,6 +914,7 @@ &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; status = "okay"; }; From fd5c78ccddc5277dccb494ef9a842d4cfd74abfe Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 24 Nov 2025 14:55:19 +0530 Subject: [PATCH 0536/1058] FROMLIST: arm64: dts: qcom: lemans-ride-common: add additional SerDes PHY regulators Add the additional 0.9V regulators for both of the Qualcomm SerDes PHYs. Link: https://lore.kernel.org/r/20251124-sgmiieth_serdes_regulator-v1-3-73ae8f9cbe2a@oss.qualcomm.com Fixes: 5ef26fb8b3ed ("arm64: dts: qcom: sa8775p-ride: enable the SerDes PHY") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi index 40f88498999bd..dcc10cc337ae4 100644 --- a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi @@ -857,11 +857,15 @@ &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; &serdes1 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; From ea46d3ef3db8349925a35246066e748608ac51cb Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:53:00 +0530 Subject: [PATCH 0537/1058] FROMLIST: arm64: dts: qcom: lemans: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in lemans. Set up CDSP cooling for both instances by throttling the cdsp, when it reaches 105°C. Signed-off-by: Gaurav Kohli Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-5-291a2ff4c634@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 126 ++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index f37512eefdb8e..850330752e117 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -7782,6 +7782,9 @@ qcom,smem-states = <&smp2p_cdsp0_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -7921,6 +7924,9 @@ qcom,smem-states = <&smp2p_cdsp1_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -8769,7 +8775,7 @@ thermal-sensors = <&tsens2 5>; trips { - trip-point0 { + nsp_0_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8781,6 +8787,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { @@ -8789,7 +8803,7 @@ thermal-sensors = <&tsens2 6>; trips { - trip-point0 { + nsp_0_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8801,6 +8815,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { @@ -8809,7 +8831,7 @@ thermal-sensors = <&tsens2 7>; trips { - trip-point0 { + nsp_0_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8821,6 +8843,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-0-thermal { @@ -8829,7 +8859,7 @@ thermal-sensors = <&tsens2 8>; trips { - trip-point0 { + nsp_1_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8841,6 +8871,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-0-thermal { @@ -8849,7 +8887,7 @@ thermal-sensors = <&tsens2 9>; trips { - trip-point0 { + nsp_1_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8861,6 +8899,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-0-thermal { @@ -8869,7 +8915,7 @@ thermal-sensors = <&tsens2 10>; trips { - trip-point0 { + nsp_1_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8881,6 +8927,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -9023,7 +9077,7 @@ thermal-sensors = <&tsens3 5>; trips { - trip-point0 { + nsp_0_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9035,6 +9089,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { @@ -9043,7 +9105,7 @@ thermal-sensors = <&tsens3 6>; trips { - trip-point0 { + nsp_0_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9055,6 +9117,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { @@ -9063,7 +9133,7 @@ thermal-sensors = <&tsens3 7>; trips { - trip-point0 { + nsp_0_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9075,6 +9145,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-1-thermal { @@ -9083,7 +9161,7 @@ thermal-sensors = <&tsens3 8>; trips { - trip-point0 { + nsp_1_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9095,6 +9173,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-1-thermal { @@ -9103,7 +9189,7 @@ thermal-sensors = <&tsens3 9>; trips { - trip-point0 { + nsp_1_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9115,6 +9201,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-1-thermal { @@ -9123,7 +9217,7 @@ thermal-sensors = <&tsens3 10>; trips { - trip-point0 { + nsp_1_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9135,6 +9229,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { From e31be3ccad6a211794b9c7195a3419e212930059 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Mon, 12 Jan 2026 13:05:20 +0530 Subject: [PATCH 0538/1058] WORKAROUND: arm64: dts: qcom: lemans-evk: Remove WCN6855 PMU node to bypass pwrseq flow There is a conflict between the current DTS configuration and the driver behavior for the WCN6855 Bluetooth path. With the PMU node in place, the driver takes the pwrseq code path unintentionally, which leads to Bluetooth failing to power up during an on -> off -> on transition. To unblock function, temporarily remove the WCN6855 PMU node so that the driver follows the non-pwrseq path and avoids the unexpected sequence. This is a TEMPORARY WORKAROUND. Once a proper M.2 binding/solution is upstreamed, will re-submit both DTS and driver changes aligned with the M.2 model. Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 73 +++---------------------- 1 file changed, 8 insertions(+), 65 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index ae6976f34bd77..183c233c1763f 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -215,63 +215,6 @@ regulator-boot-on; }; - - wcn6855-pmu { - compatible = "qcom,wcn6855-pmu"; - - vddio-supply = <&vreg_wcn_3p3>; - vddaon-supply = <&vreg_wcn_3p3>; - vddpmu-supply = <&vreg_wcn_3p3>; - vddpmumx-supply = <&vreg_wcn_3p3>; - vddpmucx-supply = <&vreg_wcn_3p3>; - vddrfa0p95-supply = <&vreg_wcn_3p3>; - vddrfa1p3-supply = <&vreg_wcn_3p3>; - vddrfa1p9-supply = <&vreg_wcn_3p3>; - vddpcielp3-supply = <&vreg_wcn_3p3>; - vddpcielp9-supply = <&vreg_wcn_3p3>; - - regulators { - vreg_pmu_rfa_cmn: ldo0 { - regulator-name = "vreg_pmu_rfa_cmn"; - }; - - vreg_pmu_aon_0p59: ldo1 { - regulator-name = "vreg_pmu_aon_0p59"; - }; - - vreg_pmu_wlcx_0p8: ldo2 { - regulator-name = "vreg_pmu_wlcx_0p8"; - }; - - vreg_pmu_wlmx_0p85: ldo3 { - regulator-name = "vreg_pmu_wlmx_0p85"; - }; - - vreg_pmu_btcmx_0p85: ldo4 { - regulator-name = "vreg_pmu_btcmx_0p85"; - }; - - vreg_pmu_rfa_0p8: ldo5 { - regulator-name = "vreg_pmu_rfa_0p8"; - }; - - vreg_pmu_rfa_1p2: ldo6 { - regulator-name = "vreg_pmu_rfa_1p2"; - }; - - vreg_pmu_rfa_1p8: ldo7 { - regulator-name = "vreg_pmu_rfa_1p8"; - }; - - vreg_pmu_pcie_0p9: ldo8 { - regulator-name = "vreg_pmu_pcie_0p9"; - }; - - vreg_pmu_pcie_1p8: ldo9 { - regulator-name = "vreg_pmu_pcie_1p8"; - }; - }; - }; }; &apps_rsc { @@ -1059,14 +1002,14 @@ compatible = "qcom,wcn6855-bt"; max-speed = <3200000>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddbtcmx-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; From fab4867a4a18624fc57ad8b7cab5782242423156 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Wed, 11 Feb 2026 13:49:19 +0530 Subject: [PATCH 0539/1058] PENDING: arm64: dts: qcom: Add EL2 support for Iris for lemans Add support for IRIS on lemans when Linux host running at EL2. Signed-off-by: Vikash Garodia --- arch/arm64/boot/dts/qcom/lemans-el2.dtso | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-el2.dtso index 621ad930cf547..3efbdda9348b3 100644 --- a/arch/arm64/boot/dts/qcom/lemans-el2.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-el2.dtso @@ -15,7 +15,9 @@ }; &iris { - status = "disabled"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { From bd6ade9c15a1d2bcee5dbc42d703008c6b2cd38c Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 16 Feb 2026 00:23:43 +0530 Subject: [PATCH 0540/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Enable wakeup for primary USB controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the "wakeup-source" property to the primary port controller node so its interrupt can wake the system from low‑power states on lemans EVK platform. Link: https://lore.kernel.org/all/20260215183325.3836178-3-swati.agarwal@oss.qualcomm.com/ Signed-off-by: Swati Agarwal --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 183c233c1763f..0a3b338136c36 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -568,6 +568,8 @@ pinctrl-0 = <&usb_id>, <&usb0_intr_state>; pinctrl-names = "default"; + wakeup-source; + ports { #address-cells = <1>; #size-cells = <0>; From b45b1b7a27132bd27d9c4eadbe5ec5024e2bb781 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Tue, 7 Apr 2026 11:07:38 +0530 Subject: [PATCH 0541/1058] PENDING: arm64: dts: qcom: lemans: switch iris iommus to iommu-map Switch the iris video codec node in sa8775p (lemans) from the legacy 'iommus' property to 'iommu-map', using IRIS_NON_PIXEL_VCODEC and IRIS_PIXEL function IDs to identify the non-pixel and pixel context bank SMMU stream mappings respectively. Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/lemans.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 850330752e117..b88d0904fac99 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -4970,8 +4971,8 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; + iommu-map = , + ; dma-coherent; status = "disabled"; From 3483f97ea03664c0f6a3e9d5b89f122fd5a8b151 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 10 Apr 2026 22:37:06 +0530 Subject: [PATCH 0542/1058] PENDING: arm64: dts: qcom: lemans-ride: Drop video firmware from common As per memory map, video firmware memory region is 7MB for sa8775* variants while it is 16MB for qcs9100* variants. Keeping the 7MB variant of video firmware in ride common DTS does not allow qcs9100* to pick the 16MB variant. Drop it from common and define in respective variant DTS. Signed-off-by: Gourav Kumar Signed-off-by: Vikash Garodia Signed-off-by: Venkata Siva Pavan KumarVenkatapatigari --- arch/arm64/boot/dts/qcom/lemans-auto.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi | 2 -- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi index 8db958d60fd1d..07fa9cb148ae6 100644 --- a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi @@ -102,3 +102,7 @@ }; }; }; + +&iris { + firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi index dcc10cc337ae4..f02aa10762c8f 100644 --- a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi @@ -582,8 +582,6 @@ }; &iris { - firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; - status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index b88d0904fac99..3fd99b131b29a 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4968,6 +4968,8 @@ memory-region = <&pil_video_mem>; + firmware-name = "qcom/vpu/vpu30_p4_s6_16mb.mbn"; + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; From fb085f052d46500663c952f13020d0c024cb75bb Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 6 Apr 2026 16:31:12 +0530 Subject: [PATCH 0543/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Rename hd3ss3220_ instance for primary port controller Rename the hd3ss3220_ instance to improve clarity and simplify usage when adding a secondary port controller. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Swati Agarwal Link: https://lore.kernel.org/r/20260406110113.1709886-2-swati.agarwal@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 0a3b338136c36..3980dbd8058a3 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -64,7 +64,7 @@ reg = <1>; usb0_con_ss_ep: endpoint { - remote-endpoint = <&hd3ss3220_in_ep>; + remote-endpoint = <&hd3ss3220_0_in_ep>; }; }; }; @@ -577,7 +577,7 @@ port@0 { reg = <0>; - hd3ss3220_in_ep: endpoint { + hd3ss3220_0_in_ep: endpoint { remote-endpoint = <&usb0_con_ss_ep>; }; }; @@ -585,7 +585,7 @@ port@1 { reg = <1>; - hd3ss3220_out_ep: endpoint { + hd3ss3220_0_out_ep: endpoint { remote-endpoint = <&usb_0_dwc3_ss>; }; }; @@ -1041,7 +1041,7 @@ }; &usb_0_dwc3_ss { - remote-endpoint = <&hd3ss3220_out_ep>; + remote-endpoint = <&hd3ss3220_0_out_ep>; }; &usb_0_hsphy { From b20022a09e59641d54c272e1292dd528ca057e80 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 6 Apr 2026 16:31:13 +0530 Subject: [PATCH 0544/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Enable secondary USB controller in host mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable secondary USB controller in host mode on lemans EVK Platform. Secondary USB controller is connected to a Genesys Logic USB HUB GL3590 having 4 ports. The ports of hub that are present on lemans EVK standalone board are used as follows:- 1) port-1 is connected to HD3SS3220 Type-C port controller. 2) port-4 is used for the M.2 E key on corekit. Standard core kit uses UART for Bluetooth. This port is to be used only if user optionally replaces the WiFi card with the NFA765 chip which uses USB for Bluetooth. Remaining 2 ports will become functional when the interface plus mezzanine board is stacked on top of corekit: 3) port-2 is connected to another hub which is present on the mezz through which 4 type-A ports are connected. 4) port-3 is used for the M.2 B key for a 5G card when the mezz is connected. Secondary USB Controller ↓ GL3590 USB Hub (4 ports) | |-- Port 1 → HD3SS3220 Type‑C Port Controller → USB‑C Connector | |-- Port 2 → Mezzanine USB Hub (when mezz attached) | |-- Port 3 → M.2 B‑Key Slot (when mezz attached) | |-- Port 4 → M.2 E‑Key Slot (Default: BT via UART; USB only if NFA765 module is installed) Mark the second USB controller as host only capable and add the HD3SS3220 Type-C port controller along with Type-C connector for controlling vbus supply. Signed-off-by: Swati Agarwal Link: https://lore.kernel.org/r/20260406110113.1709886-3-swati.agarwal@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 168 ++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 3980dbd8058a3..3a7079d302783 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -70,6 +70,37 @@ }; }; + connector-1 { + compatible = "usb-c-connector"; + label = "USB1-Type-C"; + data-role = "host"; + power-role = "source"; + + vbus-supply = <&usb1_vbus>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb1_con_hs_ep: endpoint { + remote-endpoint = <&usb_hub_2_1>; + }; + }; + + port@1 { + reg = <1>; + + usb1_con_ss_ep: endpoint { + remote-endpoint = <&hd3ss3220_1_in_ep>; + }; + + }; + }; + }; + connector-2 { compatible = "gpio-usb-b-connector", "usb-b-connector"; label = "micro-USB"; @@ -162,6 +193,15 @@ enable-active-high; }; + usb1_vbus: regulator-usb1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb1_vbus"; + gpio = <&expander1 3 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + usb2_vbus: regulator-usb2-vbus { compatible = "regulator-fixed"; regulator-name = "usb2_vbus"; @@ -591,6 +631,39 @@ }; }; }; + + usb-typec@47 { + compatible = "ti,hd3ss3220"; + reg = <0x47>; + + interrupts-extended = <&pmm8654au_2_gpios 6 IRQ_TYPE_EDGE_FALLING>; + + id-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&usb1_id>, <&usb1_intr>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hd3ss3220_1_in_ep: endpoint { + remote-endpoint = <&usb1_con_ss_ep>; + }; + }; + + port@1 { + reg = <1>; + + hd3ss3220_1_out_ep: endpoint { + remote-endpoint = <&usb_hub_3_1>; + }; + }; + }; + }; }; &i2c18 { @@ -782,6 +855,14 @@ power-source = <0>; }; + usb1_intr: usb1-intr-state { + pins = "gpio6"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; + usb2_id: usb2-id-state { pins = "gpio11"; function = "normal"; @@ -983,6 +1064,12 @@ function = "gpio"; bias-pull-up; }; + + usb1_id: usb1-id-state { + pins = "gpio51"; + function = "gpio"; + bias-pull-up; + }; }; &uart0 { @@ -1059,6 +1146,87 @@ status = "okay"; }; +&usb_1 { + dr_mode = "host"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + usb_hub_2_x: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + + peer-hub = <&usb_hub_3_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_2_1: endpoint { + remote-endpoint = <&usb1_con_hs_ep>; + }; + }; + + /* + * Port-4 is connected to M.2 E key connector on corekit. + */ + port@4 { + reg = <4>; + + usb_hub_2_4: endpoint { + }; + }; + }; + }; + + usb_hub_3_x: hub@2 { + compatible = "usb5e3,625"; + reg = <2>; + + peer-hub = <&usb_hub_2_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_3_1: endpoint { + remote-endpoint = <&hd3ss3220_1_out_ep>; + }; + }; + + port@4 { + reg = <4>; + + usb_hub_3_4: endpoint { + }; + }; + }; + }; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + &usb_2 { status = "okay"; }; From 28f09661d2c3258fea1c42cfead38b95e29849ef Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Fri, 6 Mar 2026 14:43:55 +0530 Subject: [PATCH 0545/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Enable the tertiary USB controller Enable the tertiary usb controller connected to micro usb port in OTG mode on Lemans EVK platform. Reviewed-by: Konrad Dybcio Signed-off-by: Swati Agarwal Link: https://lore.kernel.org/r/20260306091355.1178333-5-swati.agarwal@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 52 +++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 3a7079d302783..2dd10e9fdf81c 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -120,6 +120,25 @@ }; }; + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8654au_2_gpios 11 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander3 3 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + edp0-connector { compatible = "dp-connector"; label = "EDP0"; @@ -211,6 +230,15 @@ enable-active-high; }; + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8654au_1_gpios 9 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + vmmc_sdc: regulator-vmmc-sdc { compatible = "regulator-fixed"; @@ -870,6 +898,14 @@ bias-pull-up; power-source = <0>; }; + + usb2_id: usb2-id-state { + pins = "gpio11"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; }; &qup_i2c19_default { @@ -1243,6 +1279,22 @@ status = "okay"; }; +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + &xo_board_clk { clock-frequency = <38400000>; }; From 51a99d3c28e13f7a5081f0f123eb9c9f4ea026da Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 13:45:57 +0530 Subject: [PATCH 0546/1058] FROMLIST: arm64: dts: qcom: lemans: Enable audio over DISPLAY-PORT Add dailinks for DISPLAY-PORT to enable audio functionality on edp0. Link: https://lore.kernel.org/all/20260413043713.1659-1-kumar.singh@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 2dd10e9fdf81c..e565355acd0d1 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -201,6 +201,22 @@ sound-dai = <&q6apm>; }; }; + + dp0-dai-link { + link-name = "DisplayPort0 Playback"; + + codec { + sound-dai = <&mdss0_dp0>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; usb0_vbus: regulator-usb0-vbus { From c82d10a4d23d1f61e4c6e832e98140b5d1c4af7c Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 27 Feb 2026 00:29:32 +0530 Subject: [PATCH 0547/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Move SD card support to overlay The lemans EVK board supports either eMMC or SD-card, but only one can be active at a time. Move the SDHC node for SD card into a dedicated device tree overlay. This decoupling allows the storage medium to be selected dynamically by applying the appropriate overlay for either SD card or eMMC support. Link: https://lore.kernel.org/all/20260227102405.2339544-2-monish.chunara@oss.qualcomm.com/ Signed-off-by: Monish Chunara --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ .../boot/dts/qcom/lemans-evk-sd-card.dtso | 25 +++++++++++++++++++ arch/arm64/boot/dts/qcom/lemans-evk.dts | 16 ------------ 3 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..d2ead612044b8 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -44,6 +44,9 @@ dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +lemans-evk-sd-card-dtbs := lemans-evk.dtb lemans-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-sd-card.dtb + lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx577.dtbo lemans-evk-camera-dtbs := lemans-evk.dtb lemans-evk-camera.dtbo diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso new file mode 100644 index 0000000000000..007ab63473495 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&sdhc { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc_default>, <&sd_cd>; + pinctrl-1 = <&sdc_sleep>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + bus-width = <4>; + cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index e565355acd0d1..3956698d1cb6d 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -974,22 +974,6 @@ status = "okay"; }; -&sdhc { - vmmc-supply = <&vmmc_sdc>; - vqmmc-supply = <&vreg_sdc>; - - pinctrl-0 = <&sdc_default>, <&sd_cd>; - pinctrl-1 = <&sdc_sleep>, <&sd_cd>; - pinctrl-names = "default", "sleep"; - - bus-width = <4>; - cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - no-mmc; - no-sdio; - - status = "okay"; -}; - &serdes0 { phy-supply = <&vreg_l5a>; vdda-0p9-supply = <&vreg_l4a>; From e486d676071f0eefae5375653ad088a53ab4b715 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 27 Feb 2026 00:33:16 +0530 Subject: [PATCH 0548/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Add SDHCI support for eMMC via overlay Enable the SDHCI controller for eMMC functionality on the lemans EVK using a device tree overlay. Configure the corresponding addresse space and resources for eMMC. Link: https://lore.kernel.org/all/20260227102405.2339544-3-monish.chunara@oss.qualcomm.com/ Signed-off-by: Monish Chunara --- arch/arm64/boot/dts/qcom/Makefile | 3 + arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso | 64 +++++++++++++++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 10 ++- 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d2ead612044b8..3cc716919c7e6 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -44,6 +44,9 @@ dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +lemans-evk-emmc-dtbs := lemans-evk.dtb lemans-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-emmc.dtb + lemans-evk-sd-card-dtbs := lemans-evk.dtb lemans-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-sd-card.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso new file mode 100644 index 0000000000000..52739d39a1ff8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +/ { + vmmc_sdc1: regulator-l8c { + compatible = "regulator-fixed"; + regulator-name = "vreg-sdc1"; + + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + }; + + vqmmc_sdc1: regulator-s4a { + compatible = "regulator-fixed"; + regulator-name = "vqmmc-sdc1"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc { + vmmc-supply = <&vmmc_sdc1>; + vqmmc-supply = <&vqmmc_sdc1>; + + pinctrl-0 = <&sdc_default>, <&sdc_rclk>; + pinctrl-1 = <&sdc_sleep>, <&sdc_rclk_sleep>; + + pinctrl-names = "default", "sleep"; + + supports-cqe; + non-removable; + + qcom,dll-config = <0x000F64EC>; + max-frequency = <50000000>; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; + +&tlmm { + sdc_rclk: sdc1-rclk-state { + pins = "sdc1_rclk"; + bias-pull-down; + }; + + sdc_rclk_sleep: sdc1-rclk-sleep-state { + pins = "sdc1_rclk"; + drive-strength = <2>; + bias-bus-hold; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 3fd99b131b29a..6f0ae27e78074 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4309,7 +4309,9 @@ sdhc: mmc@87c4000 { compatible = "qcom,sa8775p-sdhci", "qcom,sdhci-msm-v5"; - reg = <0x0 0x087c4000 0x0 0x1000>; + reg = <0x0 0x87C4000 0x0 0x1000>, + <0x0 0x87C5000 0x0 0x1000>; + reg-names = "hc", "cqhci"; interrupts = , ; @@ -4317,9 +4319,11 @@ "pwr_irq"; clocks = <&gcc GCC_SDCC1_AHB_CLK>, - <&gcc GCC_SDCC1_APPS_CLK>; + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; clock-names = "iface", - "core"; + "core", + "xo"; interconnects = <&aggre1_noc MASTER_SDC QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, From 1fcf6045d6efcc7dca11e8c6bb495b2bd44ecf80 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:51 +0530 Subject: [PATCH 0549/1058] FROMLIST: arm64: dts: qcom: lemans: add AEST error nodes Add AEST RAS error source nodes for the Lemans SoC. The DT describes a processor error source covering all CPU cores and a shared L3 cache error source for the cluster. These nodes model the hardware error reporting blocks and associated interrupts as required by the Arm AEST specification. Link: https://lore.kernel.org/lkml/20260505-aest-devicetree-support-v1-7-d5d6ffacf0a5@oss.qualcomm.com/ Co-developed-by: Faruque Ansari Signed-off-by: Faruque Ansari Signed-off-by: Umang Chheda --- arch/arm64/boot/dts/qcom/lemans.dtsi | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 6f0ae27e78074..ca9e30fbf8b8c 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4,6 +4,7 @@ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include #include @@ -30,6 +31,46 @@ #address-cells = <2>; #size-cells = <2>; + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x0>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster1 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + }; + clocks { xo_board_clk: xo-board-clk { compatible = "fixed-clock"; From 34b382c12f6b520bdb8d780582174bf84536e9e0 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:18 +0530 Subject: [PATCH 0550/1058] FROMLIST: arm64: dts: qcom: lemans: Add GEM_NOC interconnect for adreno SMMU On Lemans platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-4-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index ca9e30fbf8b8c..fa376be108d26 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4847,6 +4847,8 @@ , , ; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; serdes0: phy@8901000 { From 3bf9719d938a83a1b538156760c8fea0b64a6fc9 Mon Sep 17 00:00:00 2001 From: Abhinaba Rakshit Date: Tue, 9 Jun 2026 03:17:28 +0530 Subject: [PATCH 0551/1058] FROMLIST: arm64: dts: qcom: lemans: Add OPP-table for ICE UFS device node Qualcomm Inline Crypto Engine (ICE) platform driver now supports an optional OPP-table. Add OPP-table for ICE UFS device nodes for LeMans platform. Signed-off-by: Abhinaba Rakshit Link: https://lore.kernel.org/r/20260609-enable-ice-clock-scaling-v11-6-1cebc8b3275b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index fa376be108d26..fcfba7d08caaa 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -3156,6 +3156,32 @@ clock-names = "core", "iface"; power-domains = <&gcc UFS_PHY_GDSC>; + + operating-points-v2 = <&ice_opp_table>; + + ice_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-75000000 { + opp-hz = /bits/ 64 <75000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; }; cryptobam: dma-controller@1dc4000 { From e3f0188c424a35545c8b1e9132b8ec5f33a7251d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 19:35:59 +0800 Subject: [PATCH 0552/1058] FROMLIST: arm64: dts: qcom: lemans: Add label properties to CoreSight devices Add label properties to TPDM and CTI nodes in the lemans device tree to provide human-readable identifiers for each CoreSight device. These labels allow userspace tools and the CoreSight framework to identify devices by name rather than by base address. Link: https://lore.kernel.org/linux-arm-msm/20260414-add-label-to-coresight-device-v2-1-5017d07358f2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/lemans.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index fcfba7d08caaa..5a219d5d6543b 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -3270,6 +3270,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3329,6 +3330,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3797,6 +3799,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3817,6 +3820,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3837,6 +3841,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3857,6 +3862,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3877,6 +3883,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3897,6 +3904,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; funnel@4b83000 { @@ -4218,6 +4226,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_actpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -4238,6 +4247,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4320,6 +4330,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4340,6 +4351,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4360,6 +4372,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_ext"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -9362,6 +9375,7 @@ turing-llm-tpdm { compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_cdsp_llm_0"; qcom,cmb-element-bits = <32>; From 81d5174e45ca9bfbff083d0c60f883076f386e18 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 24 Jun 2026 18:20:50 +0530 Subject: [PATCH 0553/1058] FROMLIST: arm64: dts: qcom: lemans: Add compatible to the PCIe Root Port Add 'compatible = "pciclass,0604"' to the pcieport0 node in lemans.dtsi to allow the PCI subsystem to associate the DT node with the PCI-to-PCI bridge device. This is required for downstream DT nodes (such as M.2 connectors described as graph endpoints of the Root Port) to be matched to PCI devices. Link: https://lore.kernel.org/r/20260622-v3-lemans-split-v3-1-d26bb22594e3@oss.qualcomm.com Reviewed-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Reviewed-by: Manivannan Sadhasivam Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/lemans.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 5a219d5d6543b..53d0347762f1d 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -2826,6 +2826,7 @@ status = "disabled"; pcieport0: pcie@0 { + compatible = "pciclass,0604"; device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; bus-range = <0x01 0xff>; From 3853a4908bb4a047bb6d096a83ca28de504b56ac Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 24 Jun 2026 18:21:03 +0530 Subject: [PATCH 0554/1058] FROMLIST: arm64: dts: qcom: lemans-evk: Describe the PCIe M.2 Key E connector The lemans EVK has the PCIe M.2 Mechanical Key E connector to connect wireless connectivity cards over PCIe and UART interfaces. Hence, describe the connector node and link it with the PCIe 0 Root Port and UART17 nodes through graph port/endpoint. The M.2 Key E connector is powered by a 3.3V fixed regulator (vreg_wcn_3p3) which is sourced from the board's 12V DC input rail (vreg_dcin_12v). Both regulators are always-on and are required by the pcie-m2-e-connector binding. Also add the serial1 = &uart17 alias, which is required for the Bluetooth serdev device to be enumerated on the UART17 interface. Link: https://lore.kernel.org/r/20260622-v3-lemans-split-v3-2-d26bb22594e3@oss.qualcomm.com Reviewed-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Reviewed-by: Manivannan Sadhasivam Reviewed-by: Konrad Dybcio Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 59 +++++++++++++++++++------ 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 3956698d1cb6d..cc66193025c6a 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -139,6 +139,38 @@ }; }; + connector-3 { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <&vreg_wcn_3p3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcieport0_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart17_ep>; + }; + }; + }; + }; + edp0-connector { compatible = "dp-connector"; label = "EDP0"; @@ -270,8 +302,8 @@ regulator-min-microvolt = <12000000>; regulator-max-microvolt = <12000000>; - regulator-boot-on; regulator-always-on; + regulator-boot-on; }; vreg_sdc: regulator-vreg-sdc { @@ -297,6 +329,7 @@ vin-supply = <&vreg_dcin_12v>; + regulator-always-on; regulator-boot-on; }; }; @@ -885,6 +918,14 @@ status = "okay"; }; +&pcieport0 { + port { + pcieport0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; +}; + &pmm8654au_0_pon_resin { linux,code = ; status = "okay"; @@ -1123,18 +1164,10 @@ &uart17 { status = "okay"; - bluetooth: bluetooth { - compatible = "qcom,wcn6855-bt"; - max-speed = <3200000>; - - vddrfacmn-supply = <&vreg_wcn_3p3>; - vddaon-supply = <&vreg_wcn_3p3>; - vddwlcx-supply = <&vreg_wcn_3p3>; - vddwlmx-supply = <&vreg_wcn_3p3>; - vddbtcmx-supply = <&vreg_wcn_3p3>; - vddrfa0p8-supply = <&vreg_wcn_3p3>; - vddrfa1p2-supply = <&vreg_wcn_3p3>; - vddrfa1p8-supply = <&vreg_wcn_3p3>; + port { + uart17_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; }; }; From aadbe4c8bd38d21cf8bfa22103313fd39fce57c1 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 9 Jun 2026 15:53:02 +0530 Subject: [PATCH 0555/1058] FROMLIST: arm64: dts: qcom: monaco: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in monaco. Set up CDSP cooling for both instances by throttling the cdsp, when it reaches 115°C. Signed-off-by: Gaurav Kohli Link: https://lore.kernel.org/r/20260609-qmi-tmd-v3-7-291a2ff4c634@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco.dtsi | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index b97a143554422..177dd8f3579e0 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -7733,6 +7733,9 @@ qcom,smem-states = <&smp2p_cdsp_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -8165,39 +8168,87 @@ }; nsp-0-0-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 5>; trips { + nsp_0_0_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 6>; trips { + nsp_0_1_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 7>; trips { + nsp_0_2_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -8285,39 +8336,87 @@ }; nsp-0-0-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 5>; trips { + nsp_0_0_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 6>; trips { + nsp_0_1_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 7>; trips { + nsp_0_2_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { From f4591533baa57e6b76741830225b4ac466fc95dd Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 21 Jan 2026 11:37:55 +0530 Subject: [PATCH 0556/1058] WORKAROUND: arm64: dts: qcom: monaco-evk: Remove WCN6855 PMU node to bypass pwrseq flow There is a conflict between the current DTS configuration and the driver behavior for the WCN6855 Bluetooth path. With the PMU node in place, the driver takes the pwrseq code path unintentionally, which leads to Bluetooth failing to power up during an on -> off -> on transition. To unblock function, temporarily remove the WCN6855 PMU node so that the driver follows the non-pwrseq path and avoids the unexpected sequence. This is a TEMPORARY WORKAROUND. Once a proper M.2 binding/solution is upstreamed, will re-submit both DTS and driver changes aligned with the M.2 model. Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 73 +++---------------------- 1 file changed, 8 insertions(+), 65 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 0eeb9154d5067..af33c7789a6ea 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -205,63 +205,6 @@ regulator-boot-on; }; - - wcn6855-pmu { - compatible = "qcom,wcn6855-pmu"; - - vddio-supply = <&vreg_wcn_3p3>; - vddaon-supply = <&vreg_wcn_3p3>; - vddpmu-supply = <&vreg_wcn_3p3>; - vddpmumx-supply = <&vreg_wcn_3p3>; - vddpmucx-supply = <&vreg_wcn_3p3>; - vddrfa0p95-supply = <&vreg_wcn_3p3>; - vddrfa1p3-supply = <&vreg_wcn_3p3>; - vddrfa1p9-supply = <&vreg_wcn_3p3>; - vddpcielp3-supply = <&vreg_wcn_3p3>; - vddpcielp9-supply = <&vreg_wcn_3p3>; - - regulators { - vreg_pmu_rfa_cmn: ldo0 { - regulator-name = "vreg_pmu_rfa_cmn"; - }; - - vreg_pmu_aon_0p59: ldo1 { - regulator-name = "vreg_pmu_aon_0p59"; - }; - - vreg_pmu_wlcx_0p8: ldo2 { - regulator-name = "vreg_pmu_wlcx_0p8"; - }; - - vreg_pmu_wlmx_0p85: ldo3 { - regulator-name = "vreg_pmu_wlmx_0p85"; - }; - - vreg_pmu_btcmx_0p85: ldo4 { - regulator-name = "vreg_pmu_btcmx_0p85"; - }; - - vreg_pmu_rfa_0p8: ldo5 { - regulator-name = "vreg_pmu_rfa_0p8"; - }; - - vreg_pmu_rfa_1p2: ldo6 { - regulator-name = "vreg_pmu_rfa_1p2"; - }; - - vreg_pmu_rfa_1p8: ldo7 { - regulator-name = "vreg_pmu_rfa_1p8"; - }; - - vreg_pmu_pcie_0p9: ldo8 { - regulator-name = "vreg_pmu_pcie_0p9"; - }; - - vreg_pmu_pcie_1p8: ldo9 { - regulator-name = "vreg_pmu_pcie_1p8"; - }; - }; - }; }; &apps_rsc { @@ -951,14 +894,14 @@ compatible = "qcom,wcn6855-bt"; max-speed = <3200000>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddbtcmx-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; From 93cebba108b0e89e713a9fbe5142ded2715311e1 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 5 Feb 2026 15:35:49 +0530 Subject: [PATCH 0557/1058] WORKAROUND: arm64: dts: qcom: monaco: Disable global IRQ for pcie1 Currently pcie1 global IRQ is blocking a CPU core, due to which ufs is getting blocked and failing. As workaround disable PCIe1 global IRQ for now. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/monaco.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 177dd8f3579e0..5bf68ea7747b5 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -2493,8 +2493,7 @@ , , , - , - ; + ; interrupt-names = "msi0", "msi1", "msi2", @@ -2502,8 +2501,7 @@ "msi4", "msi5", "msi6", - "msi7", - "global"; + "msi7"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, From 8a4a506af3e712f45fafcc726f0a7134140a4a24 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 27 Jan 2026 12:35:52 +0530 Subject: [PATCH 0558/1058] BACKPORT: arm64: dts: qcom: monaco-evk: Enable primary USB controller in host mode Enable primary USB controller in host mode on monaco EVK Platform. Primary USB controller is connected to a Genesys Logic USB HUB GL3590 having 4 ports. The ports of hub that are present on lemans EVK standalone board are used as follows:- 1) port-1 is connected to HD3SS3220 Type-C port controller. 2) port-4 is used for the M.2 E key on corekit. Standard core kit uses UART for Bluetooth. This port is to be used only if user optionally replaces the WiFi card with the NFA765 chip which uses USB for Bluetooth. Remaining 2 ports will become functional when the interface plus mezzanine board is stacked on top of corekit: 3) port-2 is connected to another hub which is present on the mezz through which 4 type-A ports are connected. 4) port-3 is used for the M.2 B key for a 5G card when the mezz is connected. Mark the second USB controller as host only capable and add the HD3SS3220 Type-C port controller along with Type-c connector for controlling vbus supply. In hardware, there are dip switches provided to operate between USB port 0 and port 1 for primary Type-C USB controller. By default, switches will be off operating at USB0 port. After bootup to HLOS, it will be operated in USB1 port. Added support in the software for both HS and SS switches as usb1-hs-high-gpio14 and usb1-ss-high-gpio5. Also, added bootup-high-gpio7 pin for USB1 hub reset to get detected after bootup. Link: https://lore.kernel.org/all/20260210152548.769951-1-loic.poulain@oss.qualcomm.com/ Signed-off-by: Loic Poulain Signed-off-by: Swati Agarwal --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 201 +++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index af33c7789a6ea..e0bc4fdb39c87 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -29,6 +29,45 @@ stdout-path = "serial0:115200n8"; }; + connector-1 { + compatible = "usb-c-connector"; + label = "USB1-Type-C"; + data-role = "host"; + power-role = "source"; + + vbus-supply = <&vbus_supply_regulator_1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb1_con_ss_ep: endpoint { + remote-endpoint = <&hd3ss3220_1_in_ep>; + }; + }; + + port@1 { + reg = <1>; + + usb1_hs_in: endpoint { + remote-endpoint = <&usb_hub_2_1>; + }; + + }; + + port@2 { + reg = <2>; + + usb1_ss_in: endpoint { + remote-endpoint = <&usb_hub_3_1>; + }; + }; + }; + }; + connector-2 { compatible = "gpio-usb-b-connector", "usb-b-connector"; label = "micro-USB"; @@ -83,6 +122,15 @@ }; }; + vbus_supply_regulator_1: regulator-vbus-supply-1 { + compatible = "regulator-fixed"; + regulator-name = "vbus_supply_1"; + gpio = <&expander1 3 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + usb2_vbus: regulator-usb2-vbus { compatible = "regulator-fixed"; regulator-name = "usb2_vbus"; @@ -483,6 +531,38 @@ }; }; }; + + usb-typec@47 { + compatible = "ti,hd3ss3220"; + reg = <0x47>; + + interrupts = <45 IRQ_TYPE_EDGE_FALLING>; + + id-gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&usb1_id>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hd3ss3220_1_in_ep: endpoint { + remote-endpoint = <&usb1_con_ss_ep>; + }; + }; + + port@1 { + reg = <1>; + + hd3ss3220_1_out_ep: endpoint { + }; + }; + }; + }; }; &i2c1 { @@ -594,6 +674,13 @@ interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; pinctrl-0 = <&expander5_int>; pinctrl-names = "default"; + + gpio5-hog { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb1-ss-high-gpio5"; + }; }; expander6: gpio@3e { @@ -606,6 +693,7 @@ interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; pinctrl-0 = <&expander6_int>; pinctrl-names = "default"; + wakeup-source; }; }; @@ -747,6 +835,20 @@ }; &tlmm { + gpio7_hog: gpio7-hog { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "bootup-high-gpio7"; + }; + + gpio14_hog: gpio14-hog { + gpio-hog; + gpios = <14 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb1-hs-high-gpio14"; + }; + pcie0_default_state: pcie0-default-state { wake-pins { pins = "gpio0"; @@ -885,6 +987,12 @@ function = "gpio"; bias-pull-up; }; + + usb1_id: usb1-id-state { + pins = "gpio13"; + function = "gpio"; + bias-pull-up; + }; }; &uart2 { @@ -931,9 +1039,100 @@ }; &usb_1 { - dr_mode = "peripheral"; + dr_mode = "host"; + + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + usb_hub_2_x: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + + peer-hub = <&usb_hub_3_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_2_1: endpoint { + remote-endpoint = <&usb1_hs_in>; + }; + }; + + /* + * Port-2 and port-3 are not connected to anything on corekit. + */ + port@2 { + reg = <2>; + + usb_hub_2_2: endpoint { + }; + }; + + port@3 { + reg = <3>; + + usb_hub_2_3: endpoint { + }; + }; + + /* + * Port-4 is connected to M.2 E key connector on corekit. + */ + port@4 { + reg = <4>; + + usb_hub_2_4: endpoint { + }; + }; + }; + }; + + usb_hub_3_x: hub@2 { + compatible = "usb5e3,625"; + reg = <2>; + + peer-hub = <&usb_hub_2_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_3_1: endpoint { + remote-endpoint = <&usb1_ss_in>; + }; + }; + + port@2 { + reg = <2>; + + usb_hub_3_2: endpoint { + }; + }; + + port@3 { + reg = <3>; + + usb_hub_3_3: endpoint { + }; + }; + + port@4 { + reg = <4>; + + usb_hub_3_4: endpoint { + }; + }; + }; + }; }; &usb_1_hsphy { From b540e0a56d7b130a417d812f08566cc431066c7b Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Mon, 30 Mar 2026 20:59:30 +0530 Subject: [PATCH 0559/1058] PENDING: arm64: dts: qcom: Add EL2 support for Iris for monaco Add support for IRIS on monaco when Linux host running at EL2. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/monaco-el2.dtso | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-el2.dtso index a7e3270f86090..7cae65ae499c3 100644 --- a/arch/arm64/boot/dts/qcom/monaco-el2.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-el2.dtso @@ -13,7 +13,10 @@ }; &iris { - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { From 6b852c2b63be46356b2de90288054778bbe03db7 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Mon, 27 Apr 2026 22:35:02 +0530 Subject: [PATCH 0560/1058] FROMLIST: arm64: dts: qcom: monaco-evk: Extract common EVK hardware into shared dtsi The monaco-ac EVK is a new board variant which shares the majority of its hardware description with the existing monaco-evk board. In preparation for adding this variant, extract the common hardware nodes from monaco-evk.dts into a new shared monaco-evk-common.dtsi include file, and update monaco-evk.dts to include it and keep only board-specific overrides. No functional change intended. Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260427170505.1494703-2-umang.chheda@oss.qualcomm.com --- .../boot/dts/qcom/monaco-evk-common.dtsi | 900 +++++++++++++ arch/arm64/boot/dts/qcom/monaco-evk.dts | 1113 +---------------- 2 files changed, 901 insertions(+), 1112 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi new file mode 100644 index 0000000000000..12c847c037572 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi @@ -0,0 +1,900 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#include "monaco.dtsi" +#include "monaco-pmics.dtsi" + +/ { + aliases { + ethernet0 = ðernet0; + i2c1 = &i2c1; + serial0 = &uart7; + serial2 = &uart6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + + dmic: audio-codec-0 { + compatible = "dmic-codec"; + #sound-dai-cells = <0>; + num-channels = <1>; + }; + + max98357a: audio-codec-1 { + compatible = "maxim,max98357a"; + #sound-dai-cells = <0>; + }; + + dp-connector-0 { + compatible = "dp-connector"; + label = "DP0"; + type = "mini"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <<8713sx_dp0_out>; + }; + }; + }; + + dp-connector-1 { + compatible = "dp-connector"; + label = "DP1"; + type = "mini"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <<8713sx_dp1_out>; + }; + }; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + + sound { + compatible = "qcom,qcs8275-sndcard"; + model = "MONACO-EVK"; + + pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; + pinctrl-names = "default"; + + hs0-mi2s-playback-dai-link { + link-name = "HS0 MI2S Playback"; + + codec { + sound-dai = <&max98357a>; + }; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + sec-mi2s-capture-dai-link { + link-name = "Secondary MI2S Capture"; + + codec { + sound-dai = <&dmic>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + vreg_cam0_2p8: vreg-cam0-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam0_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam0_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam1_2p8: vreg-cam1-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam1_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam2_2p8: vreg-cam2-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam2_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam2_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_l3a: ldo3 { + regulator-name = "vreg_l3a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4a: ldo4 { + regulator-name = "vreg_l4a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a: ldo6 { + regulator-name = "vreg_l6a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9a: ldo9 { + regulator-name = "vreg_l9a"; + regulator-min-microvolt = <2970000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_s5c: smps5 { + regulator-name = "vreg_s5c"; + regulator-min-microvolt = <1104000>; + regulator-max-microvolt = <1104000>; + regulator-initial-mode = ; + }; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <512000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4c: ldo4 { + regulator-name = "vreg_l4c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7c: ldo7 { + regulator-name = "vreg_l7c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8c: ldo8 { + regulator-name = "vreg_l8c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +ðernet0 { + phy-mode = "2500base-x"; + phy-handle = <&hsgmii_phy0>; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + nvmem-cells = <&mac_addr0>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy0: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpi_dma0 { + status = "okay"; +}; + +&gpi_dma1 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs8300/a623_zap.mbn"; +}; + +&i2c0 { + status = "okay"; + + bridge@4f { + compatible = "lontium,lt8713sx"; + reg = <0x4f>; + reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt8713sx_dp_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + + port@1 { + reg = <1>; + + lt8713sx_dp0_out: endpoint { + remote-endpoint = <&dp0_connector_in>; + }; + }; + + port@2 { + reg = <2>; + + lt8713sx_dp1_out: endpoint { + remote-endpoint = <&dp1_connector_in>; + }; + }; + }; + }; +}; + +&i2c1 { + pinctrl-0 = <&qup_i2c1_default>; + pinctrl-names = "default"; + + status = "okay"; + + fan_controller: fan@18 { + compatible = "ti,amc6821"; + reg = <0x18>; + #pwm-cells = <2>; + + fan { + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; + + eeprom0: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_addr0: mac-addr@0 { + reg = <0x0 0x6>; + }; + }; + }; +}; + +&i2c15 { + pinctrl-0 = <&qup_i2c15_default>; + pinctrl-names = "default"; + + status = "okay"; + + expander0: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander0_int>; + pinctrl-names = "default"; + }; + + expander1: gpio@39 { + compatible = "ti,tca9538"; + reg = <0x39>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander1_int>; + pinctrl-names = "default"; + }; + + expander2: gpio@3a { + compatible = "ti,tca9538"; + reg = <0x3a>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander2_int>; + pinctrl-names = "default"; + }; + + expander3: gpio@3b { + compatible = "ti,tca9538"; + reg = <0x3b>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander3_int>; + pinctrl-names = "default"; + }; + + expander4: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander4_int>; + pinctrl-names = "default"; + }; + + expander5: gpio@3d { + compatible = "ti,tca9538"; + reg = <0x3d>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander5_int>; + pinctrl-names = "default"; + }; + + expander6: gpio@3e { + compatible = "ti,tca9538"; + reg = <0x3e>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander6_int>; + pinctrl-names = "default"; + }; +}; + +&iris { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + pinctrl-0 = <&dp_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <<8713sx_dp_in>; +}; + +&mdss_dp0_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&pcie0 { + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcie1 { + pinctrl-0 = <&pcie1_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcieport0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; +}; + +&pcieport1 { + reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; +}; + +&pmm8620au_0_gpios { + usb2_id: usb2-id-state { + pins = "gpio9"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&qup_i2c0_data_clk { + drive-strength = <2>; + bias-pull-up; +}; + +&qupv3_id_0 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&qupv3_id_1 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/qcs8300/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qcs8300/cdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp { + firmware-name = "qcom/qcs8300/gpdsp0.mbn"; + + status = "okay"; +}; + +&serdes0 { + phy-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&spi10 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&tlmm { + pcie0_default_state: pcie0-default-state { + wake-pins { + pins = "gpio0"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio1"; + function = "pcie0_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + ethernet0_default: ethernet0-default-state { + ethernet0_mdc: ethernet0-mdc-pins { + pins = "gpio5"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet0_mdio: ethernet0-mdio-pins { + pins = "gpio6"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + expander5_int: expander5-int-state { + pins = "gpio3"; + function = "gpio"; + bias-pull-up; + }; + + expander1_int: expander1-int-state { + pins = "gpio16"; + function = "gpio"; + bias-pull-up; + }; + + qup_i2c1_default: qup-i2c1-state { + pins = "gpio19", "gpio20"; + function = "qup0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + pcie1_default_state: pcie1-default-state { + wake-pins { + pins = "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio22"; + function = "pcie1_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + expander3_int: expander3-int-state { + pins = "gpio24"; + function = "gpio"; + bias-pull-up; + }; + + expander6_int: expander6-int-state { + pins = "gpio52"; + function = "gpio"; + bias-pull-up; + }; + + expander0_int: expander0-int-state { + pins = "gpio56"; + function = "gpio"; + bias-pull-up; + }; + + cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { + pins = "gpio73"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { + pins = "gpio74"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { + pins = "gpio75"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + qup_i2c15_default: qup-i2c15-state { + pins = "gpio91", "gpio92"; + function = "qup1_se7"; + drive-strength = <2>; + bias-pull-up; + }; + + expander2_int: expander2-int-state { + pins = "gpio95"; + function = "gpio"; + bias-pull-up; + }; + + expander4_int: expander4-int-state { + pins = "gpio96"; + function = "gpio"; + bias-pull-up; + }; +}; + +&uart6 { + status = "okay"; +}; + +&uart7 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l7a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index e0bc4fdb39c87..87a172a25e2bc 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -5,223 +5,12 @@ /dts-v1/; -#include -#include -#include -#include - -#include "monaco.dtsi" -#include "monaco-pmics.dtsi" +#include "monaco-evk-common.dtsi" / { model = "Qualcomm Technologies, Inc. Monaco EVK"; compatible = "qcom,monaco-evk", "qcom,qcs8300"; - aliases { - ethernet0 = ðernet0; - i2c1 = &i2c1; - serial0 = &uart7; - serial1 = &uart2; - serial2 = &uart6; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - connector-1 { - compatible = "usb-c-connector"; - label = "USB1-Type-C"; - data-role = "host"; - power-role = "source"; - - vbus-supply = <&vbus_supply_regulator_1>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - usb1_con_ss_ep: endpoint { - remote-endpoint = <&hd3ss3220_1_in_ep>; - }; - }; - - port@1 { - reg = <1>; - - usb1_hs_in: endpoint { - remote-endpoint = <&usb_hub_2_1>; - }; - - }; - - port@2 { - reg = <2>; - - usb1_ss_in: endpoint { - remote-endpoint = <&usb_hub_3_1>; - }; - }; - }; - }; - - connector-2 { - compatible = "gpio-usb-b-connector", "usb-b-connector"; - label = "micro-USB"; - type = "micro"; - - id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; - vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; - vbus-supply = <&usb2_vbus>; - - pinctrl-0 = <&usb2_id>; - pinctrl-names = "default"; - - port { - usb2_con_hs_ep: endpoint { - remote-endpoint = <&usb_2_dwc3_hs>; - }; - }; - }; - - dmic: audio-codec-0 { - compatible = "dmic-codec"; - #sound-dai-cells = <0>; - num-channels = <1>; - }; - - max98357a: audio-codec-1 { - compatible = "maxim,max98357a"; - #sound-dai-cells = <0>; - }; - - dp-connector-0 { - compatible = "dp-connector"; - label = "DP0"; - type = "mini"; - - port { - dp0_connector_in: endpoint { - remote-endpoint = <<8713sx_dp0_out>; - }; - }; - }; - - dp-connector-1 { - compatible = "dp-connector"; - label = "DP1"; - type = "mini"; - - port { - dp1_connector_in: endpoint { - remote-endpoint = <<8713sx_dp1_out>; - }; - }; - }; - - vbus_supply_regulator_1: regulator-vbus-supply-1 { - compatible = "regulator-fixed"; - regulator-name = "vbus_supply_1"; - gpio = <&expander1 3 GPIO_ACTIVE_HIGH>; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - }; - - usb2_vbus: regulator-usb2-vbus { - compatible = "regulator-fixed"; - regulator-name = "usb2_vbus"; - gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - }; - - sound { - compatible = "qcom,qcs8275-sndcard"; - model = "MONACO-EVK"; - - pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; - pinctrl-names = "default"; - - hs0-mi2s-playback-dai-link { - link-name = "HS0 MI2S Playback"; - - codec { - sound-dai = <&max98357a>; - }; - - cpu { - sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - - sec-mi2s-capture-dai-link { - link-name = "Secondary MI2S Capture"; - - codec { - sound-dai = <&dmic>; - }; - - cpu { - sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - }; - - vreg_cam0_2p8: vreg-cam0-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam0_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam0_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - - vreg_cam1_2p8: vreg-cam1-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam1_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam1_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - - vreg_cam2_2p8: vreg-cam2-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam2_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam2_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - /* This comes from a PMIC handled within the SAIL domain */ vreg_s2s: vreg-s2s { compatible = "regulator-fixed"; @@ -255,557 +44,6 @@ }; }; -&apps_rsc { - regulators-0 { - compatible = "qcom,pmm8654au-rpmh-regulators"; - qcom,pmic-id = "a"; - - vreg_l3a: ldo3 { - regulator-name = "vreg_l3a"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l4a: ldo4 { - regulator-name = "vreg_l4a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l5a: ldo5 { - regulator-name = "vreg_l5a"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l6a: ldo6 { - regulator-name = "vreg_l6a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l7a: ldo7 { - regulator-name = "vreg_l7a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l8a: ldo8 { - regulator-name = "vreg_l8a"; - regulator-min-microvolt = <2504000>; - regulator-max-microvolt = <2960000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l9a: ldo9 { - regulator-name = "vreg_l9a"; - regulator-min-microvolt = <2970000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - }; - - regulators-1 { - compatible = "qcom,pmm8654au-rpmh-regulators"; - qcom,pmic-id = "c"; - - vreg_s5c: smps5 { - regulator-name = "vreg_s5c"; - regulator-min-microvolt = <1104000>; - regulator-max-microvolt = <1104000>; - regulator-initial-mode = ; - }; - - vreg_l1c: ldo1 { - regulator-name = "vreg_l1c"; - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <512000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l2c: ldo2 { - regulator-name = "vreg_l2c"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <904000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l4c: ldo4 { - regulator-name = "vreg_l4c"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l7c: ldo7 { - regulator-name = "vreg_l7c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l8c: ldo8 { - regulator-name = "vreg_l8c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l9c: ldo9 { - regulator-name = "vreg_l9c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - }; -}; - -ðernet0 { - phy-mode = "2500base-x"; - phy-handle = <&hsgmii_phy0>; - - pinctrl-0 = <ðernet0_default>; - pinctrl-names = "default"; - - snps,mtl-rx-config = <&mtl_rx_setup>; - snps,mtl-tx-config = <&mtl_tx_setup>; - nvmem-cells = <&mac_addr0>; - nvmem-cell-names = "mac-address"; - - status = "okay"; - - mdio { - compatible = "snps,dwmac-mdio"; - #address-cells = <1>; - #size-cells = <0>; - - hsgmii_phy0: ethernet-phy@1c { - compatible = "ethernet-phy-id004d.d101"; - reg = <0x1c>; - reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; - reset-assert-us = <11000>; - reset-deassert-us = <70000>; - }; - }; - - mtl_rx_setup: rx-queues-config { - snps,rx-queues-to-use = <4>; - snps,rx-sched-sp; - - queue0 { - snps,dcb-algorithm; - snps,map-to-dma-channel = <0x0>; - snps,route-up; - snps,priority = <0x1>; - }; - - queue1 { - snps,dcb-algorithm; - snps,map-to-dma-channel = <0x1>; - snps,route-ptp; - }; - - queue2 { - snps,avb-algorithm; - snps,map-to-dma-channel = <0x2>; - snps,route-avcp; - }; - - queue3 { - snps,avb-algorithm; - snps,map-to-dma-channel = <0x3>; - snps,priority = <0xc>; - }; - }; - - mtl_tx_setup: tx-queues-config { - snps,tx-queues-to-use = <4>; - - queue0 { - snps,dcb-algorithm; - }; - - queue1 { - snps,dcb-algorithm; - }; - - queue2 { - snps,avb-algorithm; - snps,send_slope = <0x1000>; - snps,idle_slope = <0x1000>; - snps,high_credit = <0x3e800>; - snps,low_credit = <0xffc18000>; - }; - - queue3 { - snps,avb-algorithm; - snps,send_slope = <0x1000>; - snps,idle_slope = <0x1000>; - snps,high_credit = <0x3e800>; - snps,low_credit = <0xffc18000>; - }; - }; -}; - -&gpi_dma0 { - status = "okay"; -}; - -&gpi_dma1 { - status = "okay"; -}; - -&gpu { - status = "okay"; -}; - -&gpu_zap_shader { - firmware-name = "qcom/qcs8300/a623_zap.mbn"; -}; - -&i2c0 { - status = "okay"; - - bridge@4f { - compatible = "lontium,lt8713sx"; - reg = <0x4f>; - reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lt8713sx_dp_in: endpoint { - remote-endpoint = <&mdss_dp0_out>; - }; - }; - - port@1 { - reg = <1>; - - lt8713sx_dp0_out: endpoint { - remote-endpoint = <&dp0_connector_in>; - }; - }; - - port@2 { - reg = <2>; - - lt8713sx_dp1_out: endpoint { - remote-endpoint = <&dp1_connector_in>; - }; - }; - }; - }; - - usb-typec@47 { - compatible = "ti,hd3ss3220"; - reg = <0x47>; - - interrupts = <45 IRQ_TYPE_EDGE_FALLING>; - - id-gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&usb1_id>; - pinctrl-names = "default"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - hd3ss3220_1_in_ep: endpoint { - remote-endpoint = <&usb1_con_ss_ep>; - }; - }; - - port@1 { - reg = <1>; - - hd3ss3220_1_out_ep: endpoint { - }; - }; - }; - }; -}; - -&i2c1 { - pinctrl-0 = <&qup_i2c1_default>; - pinctrl-names = "default"; - - status = "okay"; - - fan_controller: fan@18 { - compatible = "ti,amc6821"; - reg = <0x18>; - #pwm-cells = <2>; - - fan { - pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; - }; - }; - - eeprom0: eeprom@50 { - compatible = "atmel,24c256"; - reg = <0x50>; - pagesize = <64>; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - mac_addr0: mac-addr@0 { - reg = <0x0 0x6>; - }; - }; - }; -}; - -&i2c15 { - pinctrl-0 = <&qup_i2c15_default>; - pinctrl-names = "default"; - - status = "okay"; - - expander0: gpio@38 { - compatible = "ti,tca9538"; - reg = <0x38>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander0_int>; - pinctrl-names = "default"; - }; - - expander1: gpio@39 { - compatible = "ti,tca9538"; - reg = <0x39>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander1_int>; - pinctrl-names = "default"; - }; - - expander2: gpio@3a { - compatible = "ti,tca9538"; - reg = <0x3a>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander2_int>; - pinctrl-names = "default"; - }; - - expander3: gpio@3b { - compatible = "ti,tca9538"; - reg = <0x3b>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander3_int>; - pinctrl-names = "default"; - }; - - expander4: gpio@3c { - compatible = "ti,tca9538"; - reg = <0x3c>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander4_int>; - pinctrl-names = "default"; - }; - - expander5: gpio@3d { - compatible = "ti,tca9538"; - reg = <0x3d>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander5_int>; - pinctrl-names = "default"; - - gpio5-hog { - gpio-hog; - gpios = <5 GPIO_ACTIVE_HIGH>; - output-high; - line-name = "usb1-ss-high-gpio5"; - }; - }; - - expander6: gpio@3e { - compatible = "ti,tca9538"; - reg = <0x3e>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander6_int>; - pinctrl-names = "default"; - wakeup-source; - }; -}; - -&iris { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - -&mdss_dp0 { - pinctrl-0 = <&dp_hot_plug_det>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&mdss_dp0_out { - data-lanes = <0 1 2 3>; - link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; - remote-endpoint = <<8713sx_dp_in>; -}; - -&mdss_dp0_phy { - vdda-phy-supply = <&vreg_l5a>; - vdda-pll-supply = <&vreg_l4a>; - - status = "okay"; -}; - -&pcie0 { - pinctrl-0 = <&pcie0_default_state>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie0_phy { - vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&pcie1 { - pinctrl-0 = <&pcie1_default_state>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie1_phy { - vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&pcieport0 { - reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; -}; - -&pcieport1 { - reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; -}; - -&pmm8620au_0_gpios { - usb2_id: usb2-id-state { - pins = "gpio9"; - function = "normal"; - input-enable; - bias-pull-up; - power-source = <0>; - }; -}; - -&qup_i2c0_data_clk { - drive-strength = <2>; - bias-pull-up; -}; - -&qupv3_id_0 { - firmware-name = "qcom/qcs8300/qupv3fw.elf"; - status = "okay"; -}; - -&qupv3_id_1 { - firmware-name = "qcom/qcs8300/qupv3fw.elf"; - status = "okay"; -}; - -&remoteproc_adsp { - firmware-name = "qcom/qcs8300/adsp.mbn"; - - status = "okay"; -}; - -&remoteproc_cdsp { - firmware-name = "qcom/qcs8300/cdsp0.mbn"; - - status = "okay"; -}; - -&remoteproc_gpdsp { - firmware-name = "qcom/qcs8300/gpdsp0.mbn"; - - status = "okay"; -}; - &sdhc_1 { vmmc-supply = <&vreg_l8a>; vqmmc-supply = <&vreg_s2s>; @@ -816,352 +54,3 @@ status = "okay"; }; - -&serdes0 { - phy-supply = <&vreg_l5a>; - vdda-0p9-supply = <&vreg_l4a>; - - status = "okay"; -}; - -&spi10 { - status = "okay"; - - tpm@0 { - compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; - reg = <0>; - spi-max-frequency = <20000000>; - }; -}; - -&tlmm { - gpio7_hog: gpio7-hog { - gpio-hog; - gpios = <7 GPIO_ACTIVE_HIGH>; - output-high; - line-name = "bootup-high-gpio7"; - }; - - gpio14_hog: gpio14-hog { - gpio-hog; - gpios = <14 GPIO_ACTIVE_HIGH>; - output-high; - line-name = "usb1-hs-high-gpio14"; - }; - - pcie0_default_state: pcie0-default-state { - wake-pins { - pins = "gpio0"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - - clkreq-pins { - pins = "gpio1"; - function = "pcie0_clkreq"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-pins { - pins = "gpio2"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - ethernet0_default: ethernet0-default-state { - ethernet0_mdc: ethernet0-mdc-pins { - pins = "gpio5"; - function = "emac0_mdc"; - drive-strength = <16>; - bias-pull-up; - }; - - ethernet0_mdio: ethernet0-mdio-pins { - pins = "gpio6"; - function = "emac0_mdio"; - drive-strength = <16>; - bias-pull-up; - }; - }; - - expander5_int: expander5-int-state { - pins = "gpio3"; - function = "gpio"; - bias-pull-up; - }; - - expander1_int: expander1-int-state { - pins = "gpio16"; - function = "gpio"; - bias-pull-up; - }; - - qup_i2c1_default: qup-i2c1-state { - pins = "gpio19", "gpio20"; - function = "qup0_se1"; - drive-strength = <2>; - bias-pull-up; - }; - - pcie1_default_state: pcie1-default-state { - wake-pins { - pins = "gpio21"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - - clkreq-pins { - pins = "gpio22"; - function = "pcie1_clkreq"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-pins { - pins = "gpio23"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - expander3_int: expander3-int-state { - pins = "gpio24"; - function = "gpio"; - bias-pull-up; - }; - - expander6_int: expander6-int-state { - pins = "gpio52"; - function = "gpio"; - bias-pull-up; - }; - - expander0_int: expander0-int-state { - pins = "gpio56"; - function = "gpio"; - bias-pull-up; - }; - - cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { - pins = "gpio73"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { - pins = "gpio74"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { - pins = "gpio75"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - qup_i2c15_default: qup-i2c15-state { - pins = "gpio91", "gpio92"; - function = "qup1_se7"; - drive-strength = <2>; - bias-pull-up; - }; - - expander2_int: expander2-int-state { - pins = "gpio95"; - function = "gpio"; - bias-pull-up; - }; - - expander4_int: expander4-int-state { - pins = "gpio96"; - function = "gpio"; - bias-pull-up; - }; - - usb1_id: usb1-id-state { - pins = "gpio13"; - function = "gpio"; - bias-pull-up; - }; -}; - -&uart2 { - status = "okay"; - - bluetooth: bluetooth { - compatible = "qcom,wcn6855-bt"; - max-speed = <3200000>; - - vddrfacmn-supply = <&vreg_wcn_3p3>; - vddaon-supply = <&vreg_wcn_3p3>; - vddwlcx-supply = <&vreg_wcn_3p3>; - vddwlmx-supply = <&vreg_wcn_3p3>; - vddbtcmx-supply = <&vreg_wcn_3p3>; - vddrfa0p8-supply = <&vreg_wcn_3p3>; - vddrfa1p2-supply = <&vreg_wcn_3p3>; - vddrfa1p8-supply = <&vreg_wcn_3p3>; - }; -}; - -&uart6 { - status = "okay"; -}; - -&uart7 { - status = "okay"; -}; - -&ufs_mem_hc { - reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; - vcc-supply = <&vreg_l8a>; - vcc-max-microamp = <1100000>; - vccq-supply = <&vreg_l4c>; - vccq-max-microamp = <1200000>; - - status = "okay"; -}; - -&ufs_mem_phy { - vdda-phy-supply = <&vreg_l4a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&usb_1 { - dr_mode = "host"; - - #address-cells = <1>; - #size-cells = <0>; - - status = "okay"; - - usb_hub_2_x: hub@1 { - compatible = "usb5e3,610"; - reg = <1>; - - peer-hub = <&usb_hub_3_x>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@1 { - reg = <1>; - - usb_hub_2_1: endpoint { - remote-endpoint = <&usb1_hs_in>; - }; - }; - - /* - * Port-2 and port-3 are not connected to anything on corekit. - */ - port@2 { - reg = <2>; - - usb_hub_2_2: endpoint { - }; - }; - - port@3 { - reg = <3>; - - usb_hub_2_3: endpoint { - }; - }; - - /* - * Port-4 is connected to M.2 E key connector on corekit. - */ - port@4 { - reg = <4>; - - usb_hub_2_4: endpoint { - }; - }; - }; - }; - - usb_hub_3_x: hub@2 { - compatible = "usb5e3,625"; - reg = <2>; - - peer-hub = <&usb_hub_2_x>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@1 { - reg = <1>; - - usb_hub_3_1: endpoint { - remote-endpoint = <&usb1_ss_in>; - }; - }; - - port@2 { - reg = <2>; - - usb_hub_3_2: endpoint { - }; - }; - - port@3 { - reg = <3>; - - usb_hub_3_3: endpoint { - }; - }; - - port@4 { - reg = <4>; - - usb_hub_3_4: endpoint { - }; - }; - }; - }; -}; - -&usb_1_hsphy { - vdda-pll-supply = <&vreg_l7a>; - vdda18-supply = <&vreg_l7c>; - vdda33-supply = <&vreg_l9a>; - - status = "okay"; -}; - -&usb_qmpphy { - vdda-phy-supply = <&vreg_l7a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&usb_2 { - status = "okay"; -}; - -&usb_2_dwc3_hs { - remote-endpoint = <&usb2_con_hs_ep>; -}; - -&usb_2_hsphy { - vdda-pll-supply = <&vreg_l7a>; - vdda18-supply = <&vreg_l7c>; - vdda33-supply = <&vreg_l9a>; - - status = "okay"; -}; From b85a3901c61b4e008860eb6a728da447be776062 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 26 Jun 2026 16:43:00 +0530 Subject: [PATCH 0561/1058] FROMLIST: arm64: dts: qcom: monaco: Add monaco-ac EVK board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add initial device tree support for monaco-ac EVK board, based on Qualcomm's monaco-ac (QCS8300-AC) variant SoC. monaco-ac EVK is single board supporting these peripherals : - Storage: 1 × 128 GB UFS, micro-SD card, EEPROMs for MACs, and eMMC. - Audio/Video, Camera & Display ports. - Connectivity: RJ45 2.5GbE, WLAN/Bluetooth, CAN/CAN-FD. - PCIe ports. - USB & UART ports. Compared to "monaco-evk" variant, which utilizes higher tier QCS8300-AA SKU (supporting 40 TOPS of NPU) and a 4-PMIC (2x PM8650AU + Maxim MAX20018 + TI TPS6594) power delivery network (PDN) to support higher power requirement. This board utilizes lower tier QCS8300-AC SKU (Supporting 20 TOPS of NPU) and a simplified 2 PMIC(2x PM8650AU) PDN. Add support for the following components : - GPI (Generic Peripheral Interface) and QUPv3-0/1 controllers to facilitate DMA and peripheral communication. - TCA9534 I/O expander via I2C to provide 8 additional GPIO lines for extended I/O functionality. - USB1 controller routed to a TypeC connector in device mode to support USB peripheral operations. - Remoteproc subsystems for supported DSPs such as Audio DSP, Compute DSP and Generic DSP, along with their corresponding firmware. - Configure nvmem-layout on the I2C EEPROM to store data for Ethernet and other consumers. - QCA8081 2.5G Ethernet PHY on port-0 and expose the Ethernet MAC address via nvmem for network configuration. It depends on CONFIG_QCA808X_PHY to use QCA8081 PHY. - Support for the Iris video decoder, including the required firmware, to enable video decoding capabilities. - PCIe0 and PCIe1 controller and phy-nodes. - Sound card and max98357a based I2S speaker amplifier. Written with inputs from: Nirmesh Kumar Singh - GPIO Expander. Viken Dadhaniya - GPI/QUP. Mohd Ayaan Anwar - Ethernet. Monish Chunara - EEPROM. Swati Agarwal - USB. Sushrut Shree Trivedi - PCIe. Mohammad Rafi Shaik - Audio. Co-developed-by: Faruque Ansari Signed-off-by: Faruque Ansari Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260626111301.3479559-3-umang.chheda@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/monaco-ac-evk.dts | 938 +++++++++++++++++++++ 2 files changed, 939 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-ac-evk.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..90da4a3d4e335 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -59,6 +59,7 @@ dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb monaco-evk-camera-imx577-dtbs := monaco-evk.dtb monaco-evk-camera-imx577.dtbo diff --git a/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts new file mode 100644 index 0000000000000..6f3c3ffefe340 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts @@ -0,0 +1,938 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include +#include +#include +#include + +#include "monaco.dtsi" +#include "monaco-pmics.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Monaco-ac EVK"; + compatible = "qcom,monaco-evk", "qcom,qcs8300"; + + aliases { + ethernet0 = ðernet0; + i2c1 = &i2c1; + serial0 = &uart7; + serial2 = &uart6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + + dmic: audio-codec-0 { + compatible = "dmic-codec"; + #sound-dai-cells = <0>; + num-channels = <1>; + }; + + max98357a: audio-codec-1 { + compatible = "maxim,max98357a"; + #sound-dai-cells = <0>; + }; + + dp-connector-0 { + compatible = "dp-connector"; + label = "DP0"; + type = "mini"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <<8713sx_dp0_out>; + }; + }; + }; + + dp-connector-1 { + compatible = "dp-connector"; + label = "DP1"; + type = "mini"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <<8713sx_dp1_out>; + }; + }; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + + sound { + compatible = "qcom,qcs8275-sndcard"; + model = "MONACO-EVK"; + + pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; + pinctrl-names = "default"; + + hs0-mi2s-playback-dai-link { + link-name = "HS0 MI2S Playback"; + + codec { + sound-dai = <&max98357a>; + }; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + sec-mi2s-capture-dai-link { + link-name = "Secondary MI2S Capture"; + + codec { + sound-dai = <&dmic>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + vreg_cam0_2p8: vreg-cam0-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam0_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam0_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam1_2p8: vreg-cam1-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam1_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam2_2p8: vreg-cam2-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam2_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam2_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + /* This comes from a PMIC handled within the SAIL domain */ + vreg_s2s: vreg-s2s { + compatible = "regulator-fixed"; + regulator-name = "vreg_s2s"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_l3a: ldo3 { + regulator-name = "vreg_l3a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4a: ldo4 { + regulator-name = "vreg_l4a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a: ldo6 { + regulator-name = "vreg_l6a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9a: ldo9 { + regulator-name = "vreg_l9a"; + regulator-min-microvolt = <2970000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + vreg_s4a: smps4 { + regulator-name = "vreg_s4a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_s9a: smps9 { + regulator-name = "vreg_s9a"; + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_s5c: smps5 { + regulator-name = "vreg_s5c"; + regulator-min-microvolt = <1104000>; + regulator-max-microvolt = <1104000>; + regulator-initial-mode = ; + }; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <512000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4c: ldo4 { + regulator-name = "vreg_l4c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7c: ldo7 { + regulator-name = "vreg_l7c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8c: ldo8 { + regulator-name = "vreg_l8c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +ðernet0 { + phy-mode = "2500base-x"; + phy-handle = <&hsgmii_phy0>; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + nvmem-cells = <&mac_addr0>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy0: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpi_dma0 { + status = "okay"; +}; + +&gpi_dma1 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs8300/a623_zap.mbn"; +}; + +&i2c0 { + status = "okay"; + + bridge@4f { + compatible = "lontium,lt8713sx"; + reg = <0x4f>; + reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt8713sx_dp_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + + port@1 { + reg = <1>; + + lt8713sx_dp0_out: endpoint { + remote-endpoint = <&dp0_connector_in>; + }; + }; + + port@2 { + reg = <2>; + + lt8713sx_dp1_out: endpoint { + remote-endpoint = <&dp1_connector_in>; + }; + }; + }; + }; +}; + +&i2c1 { + pinctrl-0 = <&qup_i2c1_default>; + pinctrl-names = "default"; + + status = "okay"; + + fan_controller: fan@18 { + compatible = "ti,amc6821"; + reg = <0x18>; + #pwm-cells = <2>; + + fan { + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; + + eeprom0: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_addr0: mac-addr@0 { + reg = <0x0 0x6>; + }; + }; + }; +}; + +&i2c15 { + pinctrl-0 = <&qup_i2c15_default>; + pinctrl-names = "default"; + + status = "okay"; + + expander0: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander0_int>; + pinctrl-names = "default"; + }; + + expander1: gpio@39 { + compatible = "ti,tca9538"; + reg = <0x39>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander1_int>; + pinctrl-names = "default"; + }; + + expander2: gpio@3a { + compatible = "ti,tca9538"; + reg = <0x3a>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander2_int>; + pinctrl-names = "default"; + }; + + expander3: gpio@3b { + compatible = "ti,tca9538"; + reg = <0x3b>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander3_int>; + pinctrl-names = "default"; + }; + + expander4: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander4_int>; + pinctrl-names = "default"; + }; + + expander5: gpio@3d { + compatible = "ti,tca9538"; + reg = <0x3d>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander5_int>; + pinctrl-names = "default"; + }; + + expander6: gpio@3e { + compatible = "ti,tca9538"; + reg = <0x3e>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander6_int>; + pinctrl-names = "default"; + }; +}; + +&iris { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + pinctrl-0 = <&dp_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <<8713sx_dp_in>; +}; + +&mdss_dp0_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&pcie0 { + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcie1 { + pinctrl-0 = <&pcie1_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcieport0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; +}; + +&pcieport1 { + reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; +}; + +&pmm8620au_0_gpios { + usb2_id: usb2-id-state { + pins = "gpio9"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&qup_i2c0_data_clk { + drive-strength = <2>; + bias-pull-up; +}; + +&qupv3_id_0 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&qupv3_id_1 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/qcs8300/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qcs8300/cdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp { + firmware-name = "qcom/qcs8300/gpdsp0.mbn"; + + status = "okay"; +}; + +&sdhc_1 { + vmmc-supply = <&vreg_l8a>; + vqmmc-supply = <&vreg_s2s>; + + no-sd; + no-sdio; + non-removable; + + status = "okay"; +}; + +&serdes0 { + phy-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&spi10 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&tlmm { + pcie0_default_state: pcie0-default-state { + wake-pins { + pins = "gpio0"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio1"; + function = "pcie0_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + ethernet0_default: ethernet0-default-state { + ethernet0_mdc: ethernet0-mdc-pins { + pins = "gpio5"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet0_mdio: ethernet0-mdio-pins { + pins = "gpio6"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + expander5_int: expander5-int-state { + pins = "gpio3"; + function = "gpio"; + bias-pull-up; + }; + + expander1_int: expander1-int-state { + pins = "gpio16"; + function = "gpio"; + bias-pull-up; + }; + + qup_i2c1_default: qup-i2c1-state { + pins = "gpio19", "gpio20"; + function = "qup0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + pcie1_default_state: pcie1-default-state { + wake-pins { + pins = "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio22"; + function = "pcie1_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + expander3_int: expander3-int-state { + pins = "gpio24"; + function = "gpio"; + bias-pull-up; + }; + + expander6_int: expander6-int-state { + pins = "gpio52"; + function = "gpio"; + bias-pull-up; + }; + + expander0_int: expander0-int-state { + pins = "gpio56"; + function = "gpio"; + bias-pull-up; + }; + + cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { + pins = "gpio73"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { + pins = "gpio74"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { + pins = "gpio75"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + qup_i2c15_default: qup-i2c15-state { + pins = "gpio91", "gpio92"; + function = "qup1_se7"; + drive-strength = <2>; + bias-pull-up; + }; + + expander2_int: expander2-int-state { + pins = "gpio95"; + function = "gpio"; + bias-pull-up; + }; + + expander4_int: expander4-int-state { + pins = "gpio96"; + function = "gpio"; + bias-pull-up; + }; +}; + +&uart6 { + status = "okay"; +}; + +&uart7 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l7a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; From d3f4968b911d70ff4b5e551e4a858e50af1e5bfa Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 26 Jun 2026 16:42:59 +0530 Subject: [PATCH 0562/1058] FROMLIST: dt-bindings: arm: qcom: Add monaco-ac-evk support Introduce bindings for the monaco-ac-evk IoT board, which is based on the monaco-ac (QCS8300-AC) SoC variant. Acked-by: Krzysztof Kozlowski Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260626111301.3479559-2-umang.chheda@oss.qualcomm.com --- Documentation/devicetree/bindings/arm/qcom.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 50cc18a6ec5ed..0624560643e55 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -932,6 +932,7 @@ properties: - items: - enum: - arduino,monza + - qcom,monaco-ac-evk - qcom,monaco-evk - qcom,qcs8300-ride - const: qcom,qcs8300 From a07a2471bc43f4b801c4c34aa67325c91a2ea5a0 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Mon, 27 Apr 2026 22:35:05 +0530 Subject: [PATCH 0563/1058] FROMLIST: arm64: dts: qcom: monaco-ac-evk: Add IFP mezzanine monaco-ac-evk board supports monaco-evk-ifp-mezzanine attach. Add combined DTB for the same by merging monaco-ac-evk.dtb with monaco-evk-ifp-mezzanine overlay. Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260427170505.1494703-5-umang.chheda@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 90da4a3d4e335..1bb27df2b6b81 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -68,6 +68,9 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtb monaco-evk-el2-dtbs := monaco-evk.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-el2.dtb + +monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb From 582d20bd0e51ce5cdd805d8c506116ae1fc16ef2 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Fri, 17 Apr 2026 13:30:04 +0530 Subject: [PATCH 0564/1058] WORKAROUND: arm64: dts: qcom: monaco-evk: Use refgen regulator for usb2 HS PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem Statement:- After the Introduction of commits (1 and 2) ADB goes offline a few seconds after USB enumeration on the micro‑USB (USB2) port. The failure is consistently observed shortly after enumeration, with the following log indicating regulator shutdown: [ 40.220063][ T49] refgen: disabling On RB4, ADB operates over the USB2 HSPHY, which requires three power rails: 0.8 V (vdda‑pll) 1.8 V (vdda18) 3.3 V (vdda33) Based on the current DTS configuration, the USB2 HS PHY regulators are as follows as per monaco power grid: vdda-pll-supply (0.8 V): l7a vdda18-supply (1.8 V): l7c vdda33-supply (3.3 V): l9a However, according to the Monaco power grid analysis, the regulators for the USB2 HS PHY should be: vdda-pll-supply (0.8 V): l4a vdda18-supply (1.8 V): s4a vdda33-supply (3.3 V): l8a This mismatch in regulator assignment results in unstable PHY power, causing ADB to drop offline shortly after USB enumeration. Workaround solution:- As an interim workaround, the refgen regulator is used for the 0.8 V (vdda‑pll) rail instead of l7a. This change restores stable USB2 HS PHY operation and prevents ADB from disconnecting. Presently this is taken as a workaround while we confirm the mismatch in the power grid understanding. 1) fc406be (add Display Serial Interface device nodes) 2) 2c9e4d7 (add refgen regulator) Signed-off-by: Swati Agarwal --- arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi index 12c847c037572..45f814f059ec5 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi @@ -892,7 +892,7 @@ }; &usb_2_hsphy { - vdda-pll-supply = <&vreg_l7a>; + vdda-pll-supply = <&refgen>; vdda18-supply = <&vreg_l7c>; vdda33-supply = <&vreg_l9a>; From cc376ab55c08fea332e6260167f35ff3ba9c6e54 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 28 Apr 2026 13:54:21 +0800 Subject: [PATCH 0565/1058] FROMLIST: arm64: dts: qcom: monaco: fix wrong connection for the replicator Fix the wrong connection for the qdss replicator device. Fixes: 4f791e008807a ("arm64: dts: qcom: monaco: Add CTCU and ETR nodes") Signed-off-by: Jie Gan Link: https://lore.kernel.org/r/20260428-fix-monaco-coresight-dt-v2-1-2293259bbd10@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 5bf68ea7747b5..f5521502be39b 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -3020,14 +3020,6 @@ #address-cells = <1>; #size-cells = <0>; - port@0 { - reg = <0>; - - swao_rep_out0: endpoint { - remote-endpoint = <&qdss_rep_in>; - }; - }; - port@1 { reg = <1>; @@ -3737,6 +3729,14 @@ #address-cells = <1>; #size-cells = <0>; + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + port@1 { reg = <1>; From 9cca052c74801778e4f0dee7e9d46e301d5e1e79 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:13 +0530 Subject: [PATCH 0566/1058] FROMLIST: arm64: dts: qcom: monaco: Move eMMC CQE support from SoC to board DT The Monaco SoC SDHC controller supports both eMMC and SD cards. However, the 'supports-cqe' property (Command Queue Engine) is specific to eMMC and conflicts with SD card operation. Remove 'supports-cqe' from the SoC device tree to ensure compatibility with SD cards. Simultaneously, add the property explicitly to the qcs8300-ride and monaco-monza-som board device tree, as this board uses the controller in eMMC mode. This ensures the SoC definition remains generic while enabling features correctly at the board level. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-2-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi | 1 + arch/arm64/boot/dts/qcom/monaco.dtsi | 1 - arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi index 9b5ed55939b86..6b146fdd6ebca 100644 --- a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi @@ -275,6 +275,7 @@ mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; + supports-cqe; no-sd; no-sdio; non-removable; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index f5521502be39b..46704782a8375 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4835,7 +4835,6 @@ qcom,dll-config = <0x000f64ee>; qcom,ddr-config = <0x80040868>; bus-width = <8>; - supports-cqe; dma-coherent; mmc-ddr-1_8v; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index 4e00b1b9b562d..152a14359f2a3 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -721,6 +721,7 @@ vmmc-supply = <&vreg_l8a>; vqmmc-supply = <&vreg_s4a>; + supports-cqe; non-removable; no-sd; no-sdio; From 4b7578b7386b3749813b8b7ee0604f121a9808c3 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:14 +0530 Subject: [PATCH 0567/1058] FROMLIST: arm64: dts: qcom: monaco-evk: Enable SDHCI for SD Card via overlay The monaco EVK board supports either eMMC or SD-card, but only one can be active at a time. Enable the SD Host Controller Interface (SDHCI) on the monaco EVK board to support SD Card for storage via a device tree overlay. This allows eMMC support to be enabled through a separate overlay when required. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-3-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 4 ++ .../boot/dts/qcom/monaco-evk-sd-card.dtso | 72 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1bb27df2b6b81..9dc100ed2f196 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -73,6 +73,10 @@ monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.d dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb + +monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb + dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso new file mode 100644 index 0000000000000..bc4ea12587a2e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + vmmc_sdc: regulator-mmc-sdc { + compatible = "regulator-fixed"; + + regulator-name = "vmmc_sdc"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + }; + + vreg_sdc: regulator-sdc { + compatible = "regulator-gpio"; + + regulator-name = "vreg_sdc"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + + gpios = <&expander1 7 GPIO_ACTIVE_HIGH>; + states = <1800000 1>, <2950000 0>; + + startup-delay-us = <100>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc1_state_on>, <&sd_cd>; + pinctrl-1 = <&sdc1_state_off>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + cap-sd-highspeed; + no-1-8-v; + + bus-width = <4>; + cd-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; + +&sdhc1_opp_table { + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; +}; + +&tlmm { + sd_cd: sd-cd-state { + pins = "gpio11"; + function = "gpio"; + bias-pull-up; + }; +}; From 4eb87bab4c06c45402fd850094465d75fccf6523 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:15 +0530 Subject: [PATCH 0568/1058] FROMLIST: arm64: dts: qcom: monaco-evk: Add SDHCI support for eMMC via overlay Enable the SDHCI controller for eMMC functionality on the Monaco EVK using a device tree overlay. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-4-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 ++ arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9dc100ed2f196..2f212152f2796 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -77,6 +77,9 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb +monaco-evk-emmc-dtbs := monaco-evk.dtb monaco-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-emmc.dtb + dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso new file mode 100644 index 0000000000000..cb2566ac6923c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + vreg_s2s: regulator-vreg-s2s { + compatible = "regulator-fixed"; + regulator-name = "regulator-s2s"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vreg_l8a>; + vqmmc-supply = <&vreg_s2s>; + + supports-cqe; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + + pinctrl-names = "default", "sleep"; + + non-removable; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; From bc35e1154222435aa4a48d36e7afe4d97e3edf56 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Tue, 5 May 2026 17:53:52 +0530 Subject: [PATCH 0569/1058] FROMLIST: arm64: dts: qcom: monaco: add AEST error nodes Add AEST RAS error source nodes for the Monaco SoC. The DT describes a processor error source covering all CPU cores and a shared L3 cache error source for the cluster. These nodes model the hardware error reporting blocks and associated interrupts as required by the Arm AEST specification. Link: https://lore.kernel.org/all/20260505-aest-devicetree-support-v1-8-d5d6ffacf0a5@oss.qualcomm.com/ Co-developed-by: Faruque Ansari Signed-off-by: Faruque Ansari Signed-off-by: Umang Chheda --- arch/arm64/boot/dts/qcom/monaco.dtsi | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 46704782a8375..8cc483a0dbfa4 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -3,6 +3,7 @@ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include #include @@ -29,6 +30,46 @@ #address-cells = <2>; #size-cells = <2>; + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x0>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster1 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + }; + clocks { xo_board_clk: xo-board-clk { compatible = "fixed-clock"; From 9533749baeaa3476e4b5e48872fe30e55057d9ac Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:52 +0530 Subject: [PATCH 0570/1058] FROMLIST: arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Add pinctrl states for the GP M/N divider clock output pin across multiple Qualcomm SoCs: wire it to the GP M/N clock controller node via pinctrl-0. - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). - lemans (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). - monaco (qcs8300): Add gp_mn_active state on gpio32 (gp_mn function). Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-4-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/monaco.dtsi | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..1ff9e1598d004 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -5908,6 +5908,13 @@ function = "edp_hot"; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + mi2s0_data0: mi2s0-data0-state { pins = "gpio98"; function = "mi2s0_data0"; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb..19f8cf4e15482 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -6022,6 +6022,13 @@ bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio114", "gpio115", "gpio116", "gpio117"; function = "hs0_mi2s"; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 8cc483a0dbfa4..f5846b3bd92dc 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -6476,6 +6476,13 @@ bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio32"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio106", "gpio107", "gpio108", "gpio109"; function = "hs0_mi2s"; From 5d72f37c7e24774ca202176cd379aea5f71c2218 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:53 +0530 Subject: [PATCH 0571/1058] FROMLIST: arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Add the GP M/N divider clock controller node at 0x088d3000 to the SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. The node uses the qcom,clk-gp-mnd compatible, is clocked by the PDM XO4 and AHB clocks from GCC, and exposes a single clock output (gp_mn_clk) on the dedicated gp_mn pin mux function. The XO4 clock is pre-assigned to 4.8 MHz (XO/4). Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-5-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/qcom/monaco.dtsi | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 1ff9e1598d004..cbc13ac37f8ae 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4412,6 +4412,20 @@ }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + qspi: spi@88dc000 { compatible = "qcom,sc7280-qspi", "qcom,qspi-v1"; reg = <0 0x088dc000 0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 19f8cf4e15482..d192f92a896bb 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4353,6 +4353,20 @@ }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_0_hsphy: phy@88e4000 { compatible = "qcom,sa8775p-usb-hs-phy", "qcom,usb-snps-hs-5nm-phy"; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index f5846b3bd92dc..8ca6694c623c9 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4910,6 +4910,20 @@ }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_1_hsphy: phy@8904000 { compatible = "qcom,qcs8300-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy"; From f57788912638fc51dda09c935b944009c9959f92 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:19 +0530 Subject: [PATCH 0572/1058] FROMLIST: arm64: dts: qcom: monaco: Add GEM_NOC interconnect for adreno SMMU On Monaco platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-5-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/monaco.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 8ca6694c623c9..c67b151b09d5a 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -5145,6 +5145,8 @@ "gpu_cc_hub_aon_clk"; power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; pmu@9091000 { From e93aa15800b0cebedc8e0d79e5cf39fb32616e48 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 19:36:01 +0800 Subject: [PATCH 0573/1058] FROMLIST: arm64: dts: qcom: monaco: Add label properties to CoreSight devices Add label properties to TPDM and CTI nodes in the monaco device tree to provide human-readable identifiers for each CoreSight device. These labels allow userspace tools and the CoreSight framework to identify devices by name rather than by base address. Link: https://lore.kernel.org/linux-arm-msm/20260414-add-label-to-coresight-device-v2-3-5017d07358f2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/monaco.dtsi | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index c67b151b09d5a..791904a5164a5 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -3085,6 +3085,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3347,6 +3348,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3366,6 +3368,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_pimem"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3387,6 +3390,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_ch_south"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3480,6 +3484,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3523,6 +3528,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_mmnoc_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3595,6 +3601,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlct"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3855,6 +3862,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3874,6 +3882,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3893,6 +3902,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3912,6 +3922,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3931,6 +3942,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3950,6 +3962,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; tpdm@4b80000 { @@ -3958,6 +3971,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4025,6 +4039,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp_1"; }; tpdm@4c40000 { @@ -4033,6 +4048,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_gpdsp_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4126,6 +4142,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4198,6 +4215,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4288,6 +4306,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_ch0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4331,6 +4350,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_ch1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4656,6 +4676,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss"; }; tpdm@6860000 { @@ -4664,6 +4685,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_actpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -4683,6 +4705,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4763,6 +4786,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4782,6 +4806,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4801,6 +4826,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ext_dsb"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4820,6 +4846,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_llm_gold"; }; cti@68f0000 { @@ -4828,6 +4855,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_llm_silver"; }; cti@6900000 { @@ -4836,6 +4864,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ext_dsb"; }; sdhc_1: mmc@87c4000 { From 242b93aa7c082fc28d09a606692944e8247c29a5 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 17 Oct 2025 11:25:35 +0530 Subject: [PATCH 0574/1058] QCLINUX: arm64: dts: qcom: Add camera DT binding Add the camera DT binding header, which will be utilized by the camera downstream drivers and DTSI files. Signed-off-by: Chandan Kumar Jha --- include/dt-bindings/camera/msm-camera.h | 155 ++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 include/dt-bindings/camera/msm-camera.h diff --git a/include/dt-bindings/camera/msm-camera.h b/include/dt-bindings/camera/msm-camera.h new file mode 100644 index 0000000000000..97228c26e7040 --- /dev/null +++ b/include/dt-bindings/camera/msm-camera.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_CAMERA_H +#define __MSM_CAMERA_H + +/* CPAS path data types */ +#define CAM_CPAS_PATH_DATA_IFE_START_OFFSET 0 +#define CAM_CPAS_PATH_DATA_IFE_LINEAR (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IFE_VID (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_DISP (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_STATS (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI0 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI1 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_RDI2 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_RDI3 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_PDAF (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_RAW (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_IFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_IPE_START_OFFSET 32 +#define CAM_CPAS_PATH_DATA_IPE_RD_IN (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IPE_RD_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IPE_WR_VID (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IPE_WR_DISP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IPE_WR_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IPE_WR_APP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OPE_START_OFFSET 64 +#define CAM_CPAS_PATH_DATA_OPE_RD_IN (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OPE_RD_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OPE_WR_VID (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OPE_WR_DISP (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OPE_WR_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_SFE_START_OFFSET 96 +#define CAM_CPAS_PATH_DATA_SFE_NRDI (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_SFE_RDI0 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_SFE_RDI1 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_SFE_RDI2 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_SFE_RDI3 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_SFE_RDI4 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_SFE_STATS (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CRE_START_OFFSET (CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_RD_IN (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_CRE_WR_OUT (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OFE_START_OFFSET (CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_EXT (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_HDR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OFE_WR_VID (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OFE_WR_DISP (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OFE_WR_IR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_OFE_WR_HDR_LTM (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_OFE_WR_DC4 (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_OFE_WR_AI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_OFE_WR_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_OFE_WR_IDEALRAW (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 10) +#define CAM_CPAS_PATH_DATA_OFE_WR_STATS (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 11) +#define CAM_CPAS_PATH_DATA_OFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CONSO_OFFSET 256 +#define CAM_CPAS_PATH_DATA_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 0) + +/* IFE consolidated paths */ +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_PDAF (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI_PIXEL_RAW (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_UBWC (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PDAF_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 9) + +/* IPE Consolidated paths */ +#define CAM_CPAS_PATH_DATA_IPE_WR_VID_DISP (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) + +/* CPAS transaction types */ +#define CAM_CPAS_TRANSACTION_READ 0 +#define CAM_CPAS_TRANSACTION_WRITE 1 + +/* CPAS traffic merge types */ +#define CAM_CPAS_TRAFFIC_MERGE_SUM 0 +#define CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE 1 + +/* Feature bit type */ +#define CAM_CPAS_FEATURE_TYPE_DISABLE 0 +#define CAM_CPAS_FEATURE_TYPE_ENABLE 1 +#define CAM_CPAS_FEATURE_TYPE_VALUE 2 + +/* Feature support bit positions in feature fuse register*/ +#define CAM_CPAS_QCFA_BINNING_ENABLE 0 +#define CAM_CPAS_SECURE_CAMERA_ENABLE 1 +#define CAM_CPAS_MF_HDR_ENABLE 2 +#define CAM_CPAS_MP_LIMIT_FUSE 3 +#define CAM_CPAS_ISP_FUSE 4 +#define CAM_CPAS_ISP_PIX_FUSE 5 +#define CAM_CPAS_ISP_LITE_FUSE 6 +#define CAM_CPAS_CSIPHY_FUSE 7 +#define CAM_CPAS_IPE_VID_OUT_8BPP_LIMIT_ENABLE 8 +#define CAM_CPAS_SFE_FUSE 9 +#define CAM_CPAS_CUSTOM_FUSE 10 +#define CAM_CPAS_CAM_FUSE 11 +#define CAM_CPAS_SHDR_FUSE 12 +#define CAM_CPAS_RT_OT_FUSE 13 +#define CAM_CPAS_FUSE_FEATURE_MAX 14 + +/* Flash type*/ +#define CAM_FLASH_TYPE_PMIC 0 +#define CAM_FLASH_TYPE_I2C 1 +#define CAM_FLASH_TYPE_GPIO 2 + +/* CCI master */ +#define CCI_MASTER_0 0 +#define CCI_MASTER_1 1 +#define CCI_MASTER_MAX 2 + +/* AON Camera IDs*/ +#define AON_CAM1 0 +#define AON_CAM2 1 +#define MAX_AON_CAM 2 +#define NOT_AON_CAM 255 + +/* Camera DRV enable masks */ +#define CAM_DDR_DRV 0x1 +#define CAM_CLK_DRV 0x2 + +/* Port index for BW voting */ +#define CAM_CPAS_PORT_HLOS_DRV 0 +#define CAM_CPAS_PORT_DRV_0 1 +#define CAM_CPAS_PORT_DRV_1 2 +#define CAM_CPAS_PORT_DRV_2 3 +#define CAM_CPAS_PORT_DRV_DYN 32 + +/* Domain ID types */ +#define CAM_CPAS_NON_SECURE_DOMAIN 0 +#define CAM_CPAS_SECURE_DOMAIN 1 + +/* Debug bypass driver */ +#define CAM_BYPASS_RGLTR 0x1 +#define CAM_BYPASS_RGLTR_MODE 0x2 +#define CAM_BYPASS_CLKS 0x4 +#define CAM_BYPASS_CESTA 0x8 +#define CAM_BYPASS_ICC 0x10 + +#endif From b68eb97bed22fef5693a2879b4d01d4812dcaebe Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 10 Oct 2025 16:51:48 +0530 Subject: [PATCH 0575/1058] QCLINUX: arm64: dts: qcom: Add lemans camx overlay dts Add CAMX overlay dts file for lemans boards. This change also enables the compilation of the CAMX overlay on Lemans boards. Co-developed-by: Vikram Sharma Signed-off-by: Vikram Sharma Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 20 + .../boot/dts/qcom/lemans-camera-sensor.dtsi | 502 ++++ arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 2559 +++++++++++++++++ .../dts/qcom/lemans-evk-camera-sensor.dtsi | 736 +++++ arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso | 138 + .../boot/dts/qcom/sa8775p-ride-camx.dtso | 16 + 6 files changed, 3971 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..478deec3de5c0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -457,3 +457,23 @@ x1p42100-lenovo-thinkbook-16-el2-dtbs := x1p42100-lenovo-thinkbook-16.dtb x1-el2 dtb-$(CONFIG_ARCH_QCOM) += x1p42100-lenovo-thinkbook-16.dtb x1p42100-lenovo-thinkbook-16-el2.dtb x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb + +lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb + +qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb + +qcs9100-ride-r3-camx-dtbs:= qcs9100-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb + +sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb + +sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi new file mode 100644 index 0000000000000..d531f89dda08e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <15>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi new file mode 100644 index 0000000000000..18d78926b1f17 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -0,0 +1,2559 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci4_active>; + pinctrl-1 = <&cci4_suspend>; + pinctrl-2 = <&cci5_active>; + pinctrl-3 = <&cci5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci3: qcom,cci3@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "CCI3"; + operating-points-v2 = <&cci3_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_3_CLK_SRC>, + <&camcc CAM_CC_CCI_3_CLK>; + clock-names = "cci_3_clk_src", + "cci_3_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_3_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci6_active>; + pinctrl-1 = <&cci6_suspend>; + pinctrl-2 = <&cci7_active>; + pinctrl-3 = <&cci7_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <3>; + status = "ok"; + + cci3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci3: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci3: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci3: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci3: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + aggregator-rx; + cell-index = <0>; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3@aca2000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca2000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy3_opp_table>; + reg-cam-base = <0xa2000>; + interrupts = ; + interrupt-names = "CSIPHY3"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <3>; + aggregator-rx; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg17: qcom,tpg17@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <17>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg18: qcom,tpg18@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <18>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg19: qcom,tpg19@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <19>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "cci0", "cci1", "cci2", "cci3","csid0", "csid1", + "csid2", "csid3", "csid4", "csid5", "csid6", + "ife0", "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; + + enable-secure-qos-update; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <4>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <5>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <6>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <7>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <8>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <9>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <10>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <11>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <12>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = + ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <16>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <17>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <18>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <19>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <20>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <21>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <22>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = + ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = + ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = + ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x3400 0x0020>, + <&apps_smmu 0x3420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <4>; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + clock-control-debugfs = "true"; + cell-index = <5>; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + clock-control-debugfs = "true"; + cell-index = <6>; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&pil_camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac4d000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac5a000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x5a000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_active: cci0-active { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci4_active: cci4-active { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci4_suspend: cci4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci5_active: cci5-active { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci5_suspend: cci5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci6_active: cci6-active { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci6_suspend: cci6-suspend { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci7_active: cci7-active { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci7_suspend: cci7-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..8eb1026e7da1b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -0,0 +1,736 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0a-ov9282*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <20>; + status = "ok"; + }; + + /*cam24-ov13858*/ + qcom,cam-sensor24 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam24>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; + + eeprom_cam24: qcom,eeprom24 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <21>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <22>; + status = "ok"; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + cell-index = <15>; + compatible = "qcom,cam-gmsl-sensor"; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; + + /*cam3-ov9282*/ + qcom,cam-sensor23 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK3", + "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <23>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso new file mode 100644 index 0000000000000..520fb14660142 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso new file mode 100644 index 0000000000000..f81fa6565f281 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-camera-sensor.dtsi" From 743bfc91541cb0bdfcdb95129e58c132bb37f86e Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 17 Oct 2025 11:25:35 +0530 Subject: [PATCH 0576/1058] QCLINUX: arm64: dts: qcom: Add rb3gen2 camx overlay dts Add CAMX overlay dts file for rb3gen2 vision mezzanine board. This change also enables the compilation of the CAMX overlay for Kodiak rb3gen2 vision mezzanine board. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 5 + arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 2471 +++++++++++++++++ .../qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 551 ++++ ...qcs6490-rb3gen2-vision-mezzanine-camx.dtso | 24 + 4 files changed, 3051 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 478deec3de5c0..c336757568b57 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -462,6 +462,11 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ + qcs6490-rb3gen2-vision-mezzanine-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb + qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi new file mode 100644 index 0000000000000..f6af6827784bd --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -0,0 +1,2471 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_a5: qcom,a5 { + compatible = "qcom,cam-a5"; + cell-index = <0>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "a5_qgic", "a5_sierra", "a5_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "soc_fast_ahb", + "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <100000000 0 400000000 0>, + <200000000 0 400000000 0>, + <300000000 0 600000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "soc_fast_ahb"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "CAMERA_ICP_170.elf"; + ubwc-ipe-fetch-cfg = <0x7073 0x707b>; + ubwc-ipe-write-cfg = <0x161cf 0x161ef>; + ubwc-bps-fetch-cfg = <0x7073 0x707b>; + ubwc-bps-write-cfg = <0x161cf 0x161ef>; + qos-val = <0x00000A0A>; + status = "ok"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps { + compatible = "qcom,cam-bps"; + cell-index = <0>; + reg = <0x0 0xac6f000 0x0 0x8000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_areg_clk", + "bps_axi_clk", + "bps_clk_src", + "bps_clk"; + clock-rates = <0 0 0 200000000 0>, + <0 0 0 400000000 0>, + <0 0 0 480000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc", + "lrmecdm"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + cell-index = <0>; + label = "cpas"; + arch-compat = "cpas_top"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x0ac40000 0x0 0x1000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x9f000>; + cam_hw_fuse = , + , + , + , + , + ; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk"; + src-clock-name = "cam_cc_camnoc_axi_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0>, + <0 0 80000000 0 150000000 0 0 0>, + <0 0 80000000 0 240000000 0 0 0>, + <0 0 80000000 0 320000000 0 0 0>, + <0 0 80000000 0 400000000 0 0 0>, + <0 0 80000000 0 480000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "csiphy4", "cci0", "cci1", "csid0", "csid1", + "csid2", "csid3", "csid4", "ife0", "ife1", + "ife2", "ife3", "ife4", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", + "lrmecpas0"; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_read0>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_read0>; + }; + + ife0_pixelall_wr: ife0-pixelall-wr { + cell-index = <4>; + node-name = "ife0-pixelall-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife0_rdi_wr: ife0-rdi-wr { + cell-index = <5>; + node-name = "ife0-rdi-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_pixelall_wr: ife1-pixelall-wr { + cell-index = <6>; + node-name = "ife1-pixelall-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_wr: ife1-rdi-wr { + cell-index = <7>; + node-name = "ife1-rdi-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife2_pixelall_wr: ife2-pixelall-wr { + cell-index = <8>; + node-name = "ife2-pixelall-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write1>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <9>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife3_rdi_wr: ife3-rdi-wr { + cell-index = <10>; + node-name = "ife3-rdi-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife4_rdi_wr: ife4-rdi-wr { + cell-index = <11>; + node-name = "ife4-rdi-wr"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <12>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <13>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <14>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <15>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <16>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <17>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <18>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <19>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <20>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <21>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <22>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_nrt1_write0: level1-nrt1-write0 { + cell-index = <23>; + node-name = "level1-nrt1-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt1_read0: level1-nrt1-read0 { + cell-index = <24>; + node-name = "level1-nrt1-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <25>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <26>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write1: level1-rt1-write1 { + cell-index = <27>; + node-name = "level1-rt1-write1"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <3>; + camnoc-max-needed; + + level2_nrt0_write0: level2-nrt0-write0 { + cell-index = <28>; + node-name = "level2-nrt0-write0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt0_read0: level2-nrt0-read0 { + cell-index = <29>; + node-name = "level2-nrt0-read0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt1_read0: level2-nrt1-read0 { + cell-index = <30>; + node-name = "level2-nrt1-read0"; + parent-node = <&level3_nrt1_rd_sum>; + traffic-merge-type = + ; + bus-width-factor = <4>; + }; + + level2_rt0_write0: level2-rt0-write0 { + cell-index = <31>; + node-name = "level2-rt0-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt1_write0: level2-rt1-write0 { + cell-index = <32>; + node-name = "level2-rt1-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <33>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_SF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_nrt1_rd_sum: level3-nrt1-rd-sum { + cell-index = <34>; + node-name = "level3-nrt1-rd-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_icp"; + interconnects = + <&mmss_noc MASTER_CAMNOC_ICP 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_rt0_wr_sum: level3-rt0-wr-sum { + cell-index = <35>; + node-name = "level3-rt0-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + interconnect-names = "cam_hf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_HF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,a5", + "qcom,ipe0", + "qcom,bps"; + num-a5 = <1>; + num-ipe = <1>; + num-bps = <1>; + icp_pc_en; + status = "ok"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "ok"; + }; + + qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera_kt"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2040 0x0>; + cam-smmu-label = "cpas-cdm"; + dma-coherent; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2000 0x20>, + <&apps_smmu 0x2020 0x20>, + <&apps_smmu 0x2062 0x0>, + <&apps_smmu 0x2080 0x20>, + <&apps_smmu 0x20A0 0x20>, + <&apps_smmu 0x2140 0x0>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 5MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x500000>; + iova-region-id = <0x0>; + status = "ok"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xcf300000>; + iova-region-id = <0x3>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10a00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x800 0x4E0>, + <&apps_smmu 0x820 0x4E0>, + <&apps_smmu 0x840 0x4E0>, + <&apps_smmu 0x860 0x4E0>, + <&apps_smmu 0x880 0x4E0>, + <&apps_smmu 0x8A0 0x4E0>, + <&apps_smmu 0x8C0 0x4E0>, + <&apps_smmu 0x8E0 0x4E0>, + <&apps_smmu 0xC00 0x4E0>, + <&apps_smmu 0xC20 0x4E0>, + <&apps_smmu 0xC40 0x4E0>, + <&apps_smmu 0xC60 0x4E0>, + <&apps_smmu 0xC80 0x4E0>, + <&apps_smmu 0xCA0 0x4E0>, + <&apps_smmu 0xCC0 0x4E0>, + <&apps_smmu 0xCE0 0x4E0>; + cam-smmu-label = "ife"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x20C0 0x20>, + <&apps_smmu 0x20E0 0x20>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2100 0x20>, + <&apps_smmu 0x2120 0x20>; + cam-smmu-label = "lrme"; + dma-coherent; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_cci0: qcom,cci0 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pinctrl-0 = <&cci0_active &cci1_active>; + pinctrl-1 = <&cci0_suspend &cci1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>, + <&tlmm 72 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA0", + "CCI_I2C_CLK0", + "CCI_I2C_DATA1", + "CCI_I2C_CLK1"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4b000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4b000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pinctrl-0 = <&cci2_active &cci3_active>; + pinctrl-1 = <&cci2_suspend &cci3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 74 0>, + <&tlmm 75 0>, + <&tlmm 76 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA2", + "CCI_I2C_CLK2", + "CCI_I2C_DATA3", + "CCI_I2C_CLK3"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + qcom,cpas-cdm0 { + compatible = "qcom,cam170-cpas-cdm0"; + cell-index = <0>; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <80000000 0>; + clock-cntl-level = "svs"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cdm_cpas_opp_table>; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "ife4", "dualife"; + status = "ok"; + + cdm_cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid165_204"; + cell-index = <0>; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid165_204"; + cell-index = <1>; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid2: qcom,csid2 { + compatible = "qcom,csid165_204"; + cell-index = <2>; + reg = <0x0 0x0acc1000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xc1000>; + interrupts = ; + interrupt-names = "csid2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CSID_CLK>, + <&camcc CAM_CC_IFE_2_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid2_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite165"; + cell-index = <3>; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite165"; + cell-index = <4>; + reg = <0x0 0x0accf000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xcf000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0 { + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + cell-index = <0>; + reg = <0x0 0x0ace0000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe0000>; + interrupts = ; + interrupt-names = "csiphy0"; + operating-points-v2 = <&csiphy0_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + clock-cntl-level = "lowsvs", "svs"; + src-clock-name = "csi0phytimer_clk_src"; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1 { + cell-index = <1>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace2000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe2000>; + interrupts = ; + interrupt-names = "csiphy1"; + operating-points-v2 = <&csiphy1_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2 { + cell-index = <2>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "csiphy2"; + operating-points-v2 = <&csiphy2_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3 { + cell-index = <3>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "csiphy3"; + operating-points-v2 = <&csiphy3_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "csi3phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4 { + cell-index = <4>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "csiphy4"; + operating-points-v2 = <&csiphy4_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + cell-index = <0>; + reg = <0x0 0xac87000 0x0 0xa000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>, + <&camcc CAM_CC_IPE_0_CLK>; + clock-names = "ipe_0_ahb_clk", + "ipe_0_areg_clk", + "ipe_0_axi_clk", + "ipe_0_clk_src", + "ipe_0_clk"; + clock-rates = <0 0 0 300000000 0>, + <0 0 0 430000000 0>, + <0 0 0 520000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-430000000 { + opp-hz = /bits/ 64 <430000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-520000000 { + opp-hz = /bits/ 64 <520000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma { + compatible = "qcom,cam_jpeg_dma_165"; + cell-index = <0>; + reg = <0x0 0xac52000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x52000 0x9f000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegdma_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + cam_hw_pid = <20 21>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc { + compatible = "qcom,cam_jpeg_enc_165"; + cell-index = <0>; + reg = <0x0 0xac4e000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpege_hw", "cam_camnoc"; + reg-cam-base = <0x4e000 0x9f000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegenc_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + cam_hw_pid = <22 23>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_lrme: qcom,lrme { + compatible = "qcom,lrme"; + cell-index = <0>; + reg = <0x0 0xac6b000 0x0 0x1000>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "lrme_clk_src", + "lrme_clk"; + clock-rates = <240000000 0>, + <300000000 0>, + <320000000 0>, + <400000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + status = "ok"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,vfe0 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacaf000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xaf000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <24 8>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,vfe1 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacb6000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xb6000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <25 9>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + + cam_vfe2: qcom,vfe2 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0x0acbd000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xbd000>; + interrupts = ; + interrupt-names = "ife2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe2_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_2_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <3 10>; + cell-index = <2>; + status = "ok"; + + vfe2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,vfe-lite0 { + compatible = "qcom,vfe-lite165"; + cell-index = <3>; + reg = <0x0 0xacc4000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <11>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,vfe-lite1 { + compatible = "qcom,vfe-lite165"; + reg = <0x0 0x0accb000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xcb000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <12>; + cell-index = <4>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_active_mux: cam-sensor-active-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_active: cam_sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_active: cam-sensor-mclk5-active { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_suspend: cam-sensor-mclk5-suspend { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_mux: cam-sensor-suspend-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst0: cam_sensor-suspend-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci0_active: cci0-active { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; // Only 2 + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi new file mode 100644 index 0000000000000..8b75b1a441db4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + //cam1 interpose on dk csi0 + actuator_rear_cam11: qcom,actuator11 { + compatible = "qcom,actuator"; + cell-index = <11>; + cci-master = <1>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2856000>; + rgltr-max-voltage = <3104000>; + rgltr-load-current = <100000>; + }; + + eeprom_rear_cam11: qcom,eeprom11 { + compatible = "qcom,eeprom"; + cell-index = <11>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio", "cam_clk"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0a-ov9282*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 64 0>, + <&tlmm 20 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-ov9282*/ + qcom,cam-sensor6 { + compatible = "qcom,cam-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-imx586/imx686*/ + qcom,cam-sensor11 { + compatible = "qcom,cam-sensor"; + cell-index = <11>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + actuator-src = <&actuator_rear_cam11>; + eeprom-src = <&eeprom_rear_cam11>; + cam_vio-supply = <&vreg_l18b_1p8>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "cam_vio", "cam_clk"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + +}; + +&cam_cci1 { + eeprom_cam2: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cell-index = <8>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam3: qcom,eeprom3 { + compatible = "qcom,eeprom"; + cell-index = <0>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-position = <1>; + sensor-mode = <0>; + cci-master = <1>; + qcom,cam-power-seq-type ="cam_reset","cam_vio", + "cam_clk","cam_reset"; + qcom,cam-power-seq-val = "cam_reset","cam_vio", + "cam_mclk","cam_reset"; + qcom,cam-power-seq-cfg-val = <0 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 1 18>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam3-imx577*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + cell-index = <0>; + csiphy-sd-index = <3>; + eeprom-src = <&eeprom_cam3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 1 */ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + cell-index = <4>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_4"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 2 */ + qcom,cam-sensor5 { + compatible = "qcom,cam-sensor"; + cell-index = <5>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_5"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /*cam0b-ov9282*/ + qcom,cam-sensor7 { + compatible = "qcom,cam-sensor"; + cell-index = <7>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active + &cam_sensor_active_rst5>; + pinctrl-1 = <&cam_sensor_mclk4_suspend + &cam_sensor_suspend_rst5>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 149 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK4", + "CAM_RESET5"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + qcom,cam-sensor8 { + compatible = "qcom,cam-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam2>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 3 */ + qcom,cam-sensor9 { + compatible = "qcom,cam-sensor"; + cell-index = <9>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_9"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 4 */ + qcom,cam-sensor10 { + compatible = "qcom,cam-sensor"; + cell-index = <10>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_10"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared-pinctrl = <640>; + shared-pctrl-gpio-names = "gmsl"; + pinctrl-0 = <&cam_sensor_active_gmsl>; + pinctrl-1 = <&cam_sensor_suspend_gmsl>; + pinctrl-names = "gmsl_active", "gmsl_suspend"; + status = "ok"; + }; +}; + +&tlmm { + cam_sensor_active_gmsl: cam-sensor-active-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-up; + drive-strength = <2>; /* 2 MA */ + output-high; + }; + }; + + cam_sensor_active_rst5: cam-sensor-active-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_gmsl: cam-sensor-suspend-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst5: cam-sensor-suspend-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso new file mode 100644 index 0000000000000..eb183d7dbd3d5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; From b15b5b47bc1e8970d803695eacb96e3e56ed06b3 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Sun, 19 Oct 2025 11:20:50 +0530 Subject: [PATCH 0577/1058] QCLINUX: arm64: dts: qcom: Add monaco camx overlay dts Add CAMX overlay dts file for Monaco boards. This change also enables the compilation of the CAMX overlay for Monaco boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 8 + .../boot/dts/qcom/monaco-camera-sensor.dtsi | 380 +++ arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 2505 +++++++++++++++++ .../dts/qcom/monaco-evk-camera-sensor.dtsi | 794 ++++++ arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 107 + .../boot/dts/qcom/qcs8300-ride-camx.dtso | 16 + 6 files changed, 3810 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index c336757568b57..e9d706a1eb863 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -462,11 +462,19 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb + qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi new file mode 100644 index 0000000000000..0023c97edce91 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi new file mode 100644 index 0000000000000..bd619b507831f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -0,0 +1,2505 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci_i2c_scl3_active &cci_i2c_sda3_active>; + pinctrl-3 = <&cci_i2c_scl3_suspend &cci_i2c_sda3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl4_active &cci_i2c_sda4_active>; + pinctrl-1 = <&cci_i2c_scl4_suspend &cci_i2c_sda4_suspend>; + pinctrl-2 = <&cci_i2c_scl5_active &cci_i2c_sda5_active>; + pinctrl-3 = <&cci_i2c_scl5_suspend &cci_i2c_sda5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <0>; + aggregator-rx; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <13>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <14>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <15>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", + "cci0", "cci1", "cci2", + "csid0", "csid1", "csid2", "csid3", + "csid4", "csid5", "csid6", "ife0", + "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg13", "tpg14", "tpg15"; + enable-secure-qos-update; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <3>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <4>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <5>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <6>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <7>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <8>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <9>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <10>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <11>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <12>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <16>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <17>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <22>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <21>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <19>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <20>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + compatible = "qcom,cam-i3c-id-table"; + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2400 0x0020>, + <&apps_smmu 0x2420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + cell-index = <5>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite3"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite3"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + cell-index = <4>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite2"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite2"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + cell-index = <6>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite4"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite4"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac4d000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac60000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x60000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci-i2c-scl2-active { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci-i2c-scl2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl3_active: cci-i2c-scl3-active { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl3_suspend: cci-i2c-scl3-suspend { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl4_active: cci-i2c-scl4-active { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl4_suspend: cci-i2c-scl4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl5_active: cci-i2c-scl5-active { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl5_suspend: cci-i2c-scl5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci-i2c-sda2-active { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci-i2c-sda2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda3_active: cci-i2c-sda3-active { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda3_suspend: cci-i2c-sda3-suspend { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda4_active: cci-i2c-sda4-active { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda4_suspend: cci-i2c-sda4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda5_active: cci-i2c-sda5-active { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda5_suspend: cci-i2c-sda5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..167b85c0e8844 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi @@ -0,0 +1,794 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0-ov9282*/ + rb4_slot0: qcom,cam-sensor16 { + compatible = "qcom,cam-sensor"; + cell-index = <16>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor20 { + compatible = "qcom,cam-sensor"; + cell-index = <20>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam20>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam20: qcom,eeprom20 { + cell-index = <20>; + compatible = "qcom,eeprom"; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + rb4_slot1: qcom,cam-sensor17 { + compatible = "qcom,cam-sensor"; + cell-index = <17>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor19 { + compatible = "qcom,cam-sensor"; + cell-index = <19>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + cell-index = <21>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam19: qcom,eeprom19 { + compatible = "qcom,eeprom"; + cell-index = <19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam21: qcom,eeprom21 { + compatible = "qcom,eeprom"; + cell-index = <21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + rb4_slot2: qcom,cam-sensor18 { + compatible = "qcom,cam-sensor"; + cell-index = <18>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + cell-index = <22>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam22: qcom,eeprom22 { + compatible = "qcom,eeprom"; + cell-index = <22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + gpios-shared = <609 610 611>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso new file mode 100644 index 0000000000000..3945c77528ccb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso new file mode 100644 index 0000000000000..8f26e6dc070b0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-camera-sensor.dtsi" From 646af42ce0e934a9c4ea464b8b74ad056faf339b Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Thu, 30 Oct 2025 00:58:58 +0530 Subject: [PATCH 0578/1058] PENDING: arm64: dts: qcom: qcs8300: Update camera PIL region to 7MB The camera firmware size for IoT variant qcs8300 SoC is more than 5MB. Update the PIL memory region size of camera to 7MB to accomodate the same. Signed-off-by: Umang Chheda --- arch/arm64/boot/dts/qcom/monaco.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bd..6a374dbd09be2 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -783,7 +783,7 @@ }; camera_mem: camera-region@95200000 { - reg = <0x0 0x95200000 0x0 0x500000>; + reg = <0x0 0x95200000 0x0 0x700000>; no-map; }; From fddaf4d64ffd5456108dbdc942462f910d7917aa Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:48:22 +0530 Subject: [PATCH 0579/1058] QCLINUX: arm64: dts: qcom: Update rbgen2 camx overlay dts - Fix the indentation issue. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index f6af6827784bd..37ea48e35d09c 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -620,8 +620,8 @@ qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,a5", - "qcom,ipe0", - "qcom,bps"; + "qcom,ipe0", + "qcom,bps"; num-a5 = <1>; num-ipe = <1>; num-bps = <1>; @@ -643,7 +643,7 @@ qcom,cam-jpeg { compatible = "qcom,cam-jpeg"; compat-hw-name = "qcom,jpegenc", - "qcom,jpegdma"; + "qcom,jpegdma"; num-jpeg-enc = <1>; num-jpeg-dma = <1>; status = "ok"; From bc043cb73302547f6081f5913fe30da225b4365d Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:42:23 +0530 Subject: [PATCH 0580/1058] QCLINUX: arm64: dts: qcom: Update Monaco camx overlay dts - Fix the indentation issue. - Update DT clock property name after clock. - Short DT nodes. - Fix indexing issue. - Update gpios shared pin. Signed-off-by: Chandan Kumar Jha --- .../boot/dts/qcom/monaco-camera-sensor.dtsi | 2 +- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 204 +++++++++--------- 2 files changed, 100 insertions(+), 106 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi index 0023c97edce91..a2a2cd0a27a3a 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi @@ -374,7 +374,7 @@ &soc { qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; - gpios-shared = <518 519 520 521>; + gpios-shared = <609 610 611>; status = "ok"; }; }; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index bd619b507831f..f72161e75f7e7 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -565,8 +565,8 @@ "cam_cc_qdss_debug_xo_clk"; src-clock-name = "cam_cc_fast_ahb_clk_src"; clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, - <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, - <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; clock-cntl-level = "suspend", "svs_l1", "nominal"; clock-names-option = "cam_icp_clk"; clocks-option = <&camcc CAM_CC_ICP_CLK>; @@ -679,7 +679,7 @@ }; ife_1_wr_1: ife-1-wr-1 { - cell-index = <3>; + cell-index = <4>; node-name = "ife-1-wr-1"; client-name = "ife1"; traffic-data = ; @@ -693,7 +693,7 @@ }; ife_lite_0_wr_0: ife-lite-0-wr-0 { - cell-index = <4>; + cell-index = <5>; node-name = "ife-lite-0-wr-0"; client-name = "ife2"; traffic-data = ; @@ -707,7 +707,7 @@ }; ife_lite_1_wr_0: ife-lite-1-wr-0 { - cell-index = <5>; + cell-index = <6>; node-name = "ife-lite-1-wr-0"; client-name = "ife3"; traffic-data = ; @@ -721,7 +721,7 @@ }; ife_lite_2_wr_0: ife-lite-2-wr-0 { - cell-index = <6>; + cell-index = <7>; node-name = "ife-lite-2-wr-0"; client-name = "ife4"; traffic-data = ; @@ -735,7 +735,7 @@ }; ife_lite_3_wr_0: ife-lite-3-wr-0 { - cell-index = <7>; + cell-index = <8>; node-name = "ife-lite-3-wr-0"; client-name = "ife5"; traffic-data = ; @@ -749,7 +749,7 @@ }; ife_lite_4_wr_0: ife-lite-4-wr-0 { - cell-index = <8>; + cell-index = <9>; node-name = "ife-lite-4-wr-0"; client-name = "ife6"; traffic-data = ; @@ -763,7 +763,7 @@ }; ipe_0_rd_all: ipe-0-rd-all { - cell-index = <9>; + cell-index = <10>; node-name = "ipe-0-rd-all"; client-name = "ipe0"; traffic-data = ; @@ -774,7 +774,7 @@ }; ipe_0_wr_2: ipe-0-wr-2 { - cell-index = <10>; + cell-index = <11>; node-name = "ipe-0-wr-2"; client-name = "ipe0"; traffic-data = ; @@ -787,7 +787,7 @@ }; ipe_cdm0_all_rd: ipe-cdm0-all-rd { - cell-index = <11>; + cell-index = <12>; node-name = "ipe-cdm0-all-rd"; client-name = "ipe0"; traffic-data = ; @@ -796,7 +796,7 @@ }; rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { - cell-index = <12>; + cell-index = <13>; node-name = "rt-cdm0-all-rd-2"; client-name = "rt-cdm0"; traffic-data = ; @@ -805,7 +805,7 @@ }; rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { - cell-index = <13>; + cell-index = <14>; node-name = "rt-cdm1-all-rd-2"; client-name = "rt-cdm1"; traffic-data = ; @@ -814,7 +814,7 @@ }; rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { - cell-index = <14>; + cell-index = <15>; node-name = "rt-cdm2-all-rd-2"; client-name = "rt-cdm2"; traffic-data = ; @@ -823,7 +823,7 @@ }; rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { - cell-index = <15>; + cell-index = <16>; node-name = "rt-cdm3-all-rd-2"; client-name = "rt-cdm3"; traffic-data = ; @@ -832,7 +832,7 @@ }; sfe_0_rd_0: sfe-0-rd-0 { - cell-index = <16>; + cell-index = <17>; node-name = "sfe-0-rd-0"; client-name = "sfe0"; traffic-data = ; @@ -842,7 +842,7 @@ }; sfe_1_rd_0: sfe-1-rd-0 { - cell-index = <17>; + cell-index = <18>; node-name = "sfe-1-rd-0"; client-name = "sfe1"; traffic-data = ; @@ -857,28 +857,28 @@ camnoc-max-needed; level1_nrt_rd2: level1-nrt-rd2 { - cell-index = <22>; + cell-index = <19>; node-name = "level1-nrt-rd2"; parent-node = <&level2_nrt_rd2>; traffic-merge-type = ; }; level1_rt_rd0: level1-rt-read0 { - cell-index = <21>; + cell-index = <20>; node-name = "level1-rt-rd0"; parent-node = <&level2_rt_rd0>; traffic-merge-type = ; }; level1_rt_wr0: level1-rt-wr0 { - cell-index = <19>; + cell-index = <21>; node-name = "level1-rt-wr0"; parent-node = <&level2_rt_wr0>; traffic-merge-type = ; }; level1_rt_wr1: level1-rt-wr1 { - cell-index = <20>; + cell-index = <22>; node-name = "level1-rt-wr1"; parent-node = <&level2_rt_wr1>; traffic-merge-type = ; @@ -978,8 +978,7 @@ qcom,cam-icp { compatible = "qcom,cam-icp"; - compat-hw-name = "qcom,icp", - "qcom,ipe0"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; num-ipe = <1>; icp_use_pil; @@ -1023,6 +1022,7 @@ cam-smmu-label = "rt-cdm"; dma-coherent; multiple-client-devices; + rt_cdm_iova_mem_map: iova-mem-map { iova-mem-region-io { /* IO region is approximately 4.0 GB */ @@ -1059,6 +1059,7 @@ iova-region-id = <0x6>; subregion_support; status = "ok"; + /* Used for HFI queues/sec heap */ iova-mem-region-generic-region { iova-region-name = "icp_hfi"; @@ -1096,7 +1097,6 @@ iova-region-id = <0x1>; status = "ok"; }; - }; }; @@ -1298,49 +1298,46 @@ }; }; - cam_csid_lite3: qcom,csid-lite3 { - cell-index = <5>; + cam_csid_lite2: qcom,csid-lite2 { compatible = "qcom,csid-lite692"; - reg-names = "csid-lite3"; - reg = <0x0 0xac90000 0x0 0xf01>; - reg-cam-base = <0x90000>; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite3"; - interrupts = ; + interrupts = ; + interrupt-names = "csid-lite2"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; - operating-points-v2 = <&csid_lite3_opp_table>; - + operating-points-v2 = <&csid_lite2_opp_table>; clock-control-debugfs = "true"; + cell-index = <4>; status = "ok"; - csid_lite3_opp_table: opp-table { + csid_lite2_opp_table: opp-table { compatible = "operating-points-v2"; opp-400000000 { opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1348,49 +1345,46 @@ }; }; - cam_csid_lite2: qcom,csid-lite2 { - cell-index = <4>; + cam_csid_lite3: qcom,csid-lite3 { compatible = "qcom,csid-lite692"; - reg-names = "csid-lite2"; - reg = <0x0 0xac8c000 0x0 0xf01>; - reg-cam-base = <0x8c000>; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite2"; - interrupts = ; + interrupts = ; + interrupt-names = "csid-lite3"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; - operating-points-v2 = <&csid_lite2_opp_table>; - + operating-points-v2 = <&csid_lite3_opp_table>; clock-control-debugfs = "true"; + cell-index = <5>; status = "ok"; - csid_lite2_opp_table: opp-table { + csid_lite3_opp_table: opp-table { compatible = "operating-points-v2"; opp-400000000 { opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1399,39 +1393,35 @@ }; cam_csid_lite4: qcom,csid-lite4 { - cell-index = <6>; compatible = "qcom,csid-lite692"; - reg-names = "csid-lite4"; reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; reg-cam-base = <0x94000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite4"; interrupts = ; + interrupt-names = "csid-lite4"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; operating-points-v2 = <&csid_lite4_opp_table>; - clock-control-debugfs = "true"; + cell-index = <6>; status = "ok"; csid_lite4_opp_table: opp-table { @@ -1441,6 +1431,7 @@ opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1489,6 +1480,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1532,6 +1524,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1575,6 +1568,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; From 6de787f6ac3495d6ce33d2dfd8114122cb95329d Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:36:51 +0530 Subject: [PATCH 0581/1058] QCLINUX: arm64: dts: qcom: Update Lemans camx overlay dts - Fix the indentation issue. - Update DT clock property name after clock. - Shorted DT nodes. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 43 +++++++++------------ 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index 18d78926b1f17..855d29dff618f 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -743,7 +743,6 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; - enable-secure-qos-update; cell-index = <0>; status = "ok"; @@ -817,7 +816,6 @@ parent-node = <&level1_rt_wr0>; }; - ife_1_wr_1: ife-1-wr-1 { cell-index = <4>; node-name = "ife-1-wr-1"; @@ -958,8 +956,7 @@ node-name = "rt-cdm2-all-rd-2"; client-name = "rt-cdm2"; traffic-data = ; - traffic-transaction-type = - ; + traffic-transaction-type = ; parent-node = <&level1_nrt_rd2>; }; @@ -1086,8 +1083,7 @@ level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { cell-index = <30>; node-name = "level3-nrt0-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; qcom,axi-port-mnoc { cam-icc-path-names = "cam_sf_0"; @@ -1097,8 +1093,7 @@ level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { cell-index = <31>; node-name = "level3-nrt1-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; qcom,axi-port-mnoc { cam-icc-path-names = "cam_sf_icp"; @@ -1108,8 +1103,7 @@ level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { cell-index = <32>; node-name = "level3-rt-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; ib-bw-voting-needed; qcom,axi-port-mnoc { @@ -1148,8 +1142,8 @@ status = "ok"; }; - qcom,cam-sync { - compatible = "qcom,cam-sync"; + qcom,camera-main { + compatible = "qcom,camera"; status = "ok"; }; @@ -1274,8 +1268,8 @@ }; }; - qcom,camera-main { - compatible = "qcom,camera"; + qcom,cam-sync { + compatible = "qcom,cam-sync"; status = "ok"; }; @@ -1544,13 +1538,6 @@ interrupts = ; interrupt-names = "csid-lite4"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>, <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, @@ -1558,6 +1545,13 @@ <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, <&camcc CAM_CC_IFE_LITE_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; clock-rates = <0 0 400000000 0 0 400000000 0>, <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; @@ -2000,7 +1994,6 @@ required-opps = <&rpmhpd_opp_nom>; }; }; - }; qcom,rt-cdm0 { @@ -2140,12 +2133,12 @@ interrupts = ; interrupt-names = "sfe-lite0"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", - "cam_cc_sfe_lite_0_clk", - "cam_cc_cpas_sfe_lite_0_clk"; clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, <&camcc CAM_CC_SFE_LITE_0_CLK>, <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; clock-rates = <0 480000000 300000000>, <0 600000000 400000000>; clock-cntl-level = "svs_l1", "nominal"; From 5e1cf2f2f60cacfd55beff434f716b084bf2c110 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 24 Dec 2025 14:00:56 +0800 Subject: [PATCH 0582/1058] PENDING: arm64: dts: qcom: change pil camera memory map Add the pil camera carveout region based on v2 memory map. Signed-off-by: Qingqing Zhou Signed-off-by: Xin Liu --- arch/arm64/boot/dts/qcom/talos.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index fb1bbc51bb8a4..f72ac36d53dfc 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -677,6 +677,11 @@ reg = <0x0 0x97715000 0x0 0x2000>; no-map; }; + + pil_camera_mem: pil-camera-region@97717000 { + reg = <0x0 0x97717000 0x0 0x800000>; + no-map; + }; }; soc: soc@0 { From 7341a83d8ca10f8066bbc4ff353457894f9c34f3 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 24 Dec 2025 16:16:57 +0530 Subject: [PATCH 0583/1058] QCLINUX: arm64: dts: qcom: Add Talos camx overlay dts Add CAMX overlay dts file for Talos boards. This change also enables the compilation of the CAMX overlay on Talos boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../arm64/boot/dts/qcom/qcs615-ride-camx.dtso | 16 + .../boot/dts/qcom/talos-camera-sensor.dtsi | 152 ++ arch/arm64/boot/dts/qcom/talos-camera.dtsi | 1984 +++++++++++++++++ 4 files changed, 2156 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/talos-camera.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e9d706a1eb863..9eacf8c4e60f7 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -466,6 +466,10 @@ monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi new file mode 100644 index 0000000000000..7e76197614781 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci { + /*cam0-imx577*/ + tl_slot0: qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam0>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577*/ + t1_slot1: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam1>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; + + /*cam0-imx577-eeprom*/ + eeprom_cam0: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577-eeprom*/ + eeprom_cam1: qcom,eeprom1 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi new file mode 100644 index 0000000000000..e2daa14db1e80 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -0,0 +1,1984 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v1"; + icp-version = <0x0100>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "icp_qgic", "icp_sierra", "icp_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_clk", + "cam_cc_icp_clk_src"; + clock-rates = <0 0 100000000 0 0 0 0 240000000>, + <0 0 200000000 0 0 0 0 360000000>, + <0 0 300000000 0 0 0 0 432000000>, + <0 0 404000000 0 0 0 0 480000000>, + <0 0 404000000 0 0 0 0 540000000>, + <0 0 404000000 0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_icp_clk_src"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "CAMERA_ICP.elf"; + ubwc-cfg = <0x73 0x1CF>; + cam_hw_pid = <15>; + cell-index = <0>; + status = "okay"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cpas@ac40000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac40000 0x0 0x1000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x42000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0>, + <0 0 0 80000000 0 150000000>, + <0 0 0 80000000 0 240000000>, + <0 0 0 80000000 0 265000000>, + <0 0 0 80000000 0 355000000>, + <0 0 0 80000000 0 426000000>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_camnoc_axi_clk"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_HF1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cam_ahb", + "cam_hf_0_mnoc", + "cam_hf_1_mnoc", + "cam_sf_0_mnoc"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", + "svs_l1", "nominal", "nominal", + "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "cci0", + "csid0", "csid1", "csid2","ife0", + "ife1", "ife2", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "lrmecpas0"; + cell-index = <0>; + status = "okay"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-265000000 { + opp-hz = /bits/ 64 <265000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-355000000 { + opp-hz = /bits/ 64 <355000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-426000000 { + opp-hz = /bits/ 64 <426000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read2>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read3>; + }; + + ife0_linear_pdaf_wr: ife0-linear-pdaf-wr { + cell-index = <4>; + node-name = "ife0-linear-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_ubwc_stats_wr: ife0-ubwc-stats-wr { + cell-index = <6>; + node-name = "ife0-ubwc-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_linear_pdaf_wr: ife1-linear-pdaf-wr { + cell-index = <7>; + node-name = "ife1-linear-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <8>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_ubwc_stats_wr: ife1-ubwc-stats-wr { + cell-index = <9>; + node-name = "ife1-ubwc-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <10>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <11>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <12>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <13>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <14>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = + ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <15>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <16>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <17>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <18>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <19>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <20>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read1: level1-nrt0-read1 { + cell-index = <21>; + node-name = "level1-nrt0-read1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read2: level1-nrt0-read2 { + cell-index = <22>; + node-name = "level1-nrt0-read2"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read3: level1-nrt0-read3 { + cell-index = <23>; + node-name = "level1-nrt0-read3"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <24>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write1: level1-nrt0-write1 { + cell-index = <25>; + node-name = "level1-nrt0-write1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <26>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <27>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + + level2_nrt0_rd_wr_sum: level2-nrt0-rd-wr-sum { + cell-index = <28>; + node-name = "level2-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0_mnoc"; + }; + }; + + level2_rt0_rd_wr_sum: level2-rt0-rd-wr-sum { + cell-index = <29>; + node-name = "level2-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0_mnoc"; + }; + }; + + level2_rt1_rd_wr_sum: level2-rt1-rd-wr-sum { + cell-index = <30>; + node-name = "level3-rt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_1_mnoc"; + }; + }; + }; + }; + }; + + qcom,cpas-cdm0@ac48000 { + compatible = "qcom,cam170-cpas-cdm0"; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_slow_ahb_clk_src"; + clock-rates = <0 0 0 0 0 80000000>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cpas_cdm_opp_table>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "dualife"; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cpas_cdm_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_cci: qcom,cci@ac4a000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x4000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "CCI"; + operating-points-v2 = <&cci_opp_table>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_CLK_SRC>, + <&camcc CAM_CC_CCI_CLK>; + clock-names = "cci_clk_src", + "cci_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "okay"; + + cci_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac4e000 { + compatible = "qcom,cam_jpeg_enc_170"; + reg = <0x0 0xac4e000 0x0 0x4000>; + reg-names = "jpege_hw"; + reg-cam-base = <0x4e000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac52000{ + compatible = "qcom,cam_jpeg_dma_170"; + reg = <0x0 0xac52000 0x0 0x4000>; + reg-names = "jpegdma_hw"; + reg-cam-base = <0x52000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy@ac65000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0x0ac65000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x65000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy@ac66000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac66000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x66000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy@ac67000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac67000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0x67000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_lrme: qcom,lrme@ac6b000 { + compatible = "qcom,lrme"; + reg = <0x0 0xac6b000 0x0 0xa00>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_lrme_clk_src", + "cam_cc_lrme_clk"; + clock-rates = <0 0 0 0 0 200000000 0>, + <0 0 0 0 0 216000000 0>, + <0 0 0 0 0 300000000 0>, + <0 0 0 0 0 404000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "cam_cc_lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + cam_hw_pid = <6 10>; + cell-index = <0>; + status = "okay"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-216000000 { + opp-hz = /bits/ 64 <216000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@0x0ac6f000 { + compatible = "qcom,cam-bps"; + reg = <0x0 0xac6f000 0x0 0x3000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>; + clock-names = "cam_cc_bps_ahb_clk", + "cam_cc_bps_areg_clk", + "cam_cc_bps_axi_clk", + "cam_cc_bps_clk", + "cam_cc_bps_clk_src"; + clock-rates = <0 0 0 0 200000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + cam_hw_pid = <5 9>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@0x0ac87000 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac87000 0x0 0x3000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc IPE_0_GDSC>; + clock-names = "cam_cc_ipe_0_ahb_clk", + "cam_cc_ipe_0_areg_clk", + "cam_cc_ipe_0_axi_clk", + "cam_cc_ipe_0_clk", + "cam_cc_ipe_0_clk_src"; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>; + clock-rates = <0 0 0 0 240000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs","svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + cam_hw_pid = <4 8>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe0: qcom,vfe0@acaf000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacaf000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0xaf000 0x42000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-names-option = "cam_cc_ife_0_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <1>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb3000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid0"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_csid_clk", + "cam_cc_ife_0_csid_clk_src", + "cam_cc_ife_0_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + operating-points-v2 = <&csid0_opp_table>; + src-clock-name = "cam_cc_ife_0_csid_clk_src"; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe1: qcom,vfe1@acb6000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacb6000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0xb6000 0x42000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-names-option = "cam_cc_ife_1_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <2>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid1: qcom,csid1@acba000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid1"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_csid_clk", + "cam_cc_ife_1_csid_clk_src", + "cam_cc_ife_1_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_1_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe_lite: qcom,vfe-lite@acc4000 { + compatible = "qcom,vfe-lite170"; + reg = <0x0 0xacc4000 0x0 0x4000>; + reg-names = "ife-lite0"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0>, + <0 0 0 0 0 0 360000000 0>, + <0 0 0 0 0 0 432000000 0>, + <0 0 0 0 0 0 540000000 0>, + <0 0 0 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + cam_hw_pid = <3>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid_lite: qcom,csid-lite@acc8000 { + compatible = "qcom,csid-lite170"; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite0"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", "jpegdma", + "jpegenc", "lrmecdm"; + status = "okay"; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + ipe0-mask = <0x1000>; + icp_pc_en; + status = "okay"; + }; + + cam_isp_mgr: qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + cam_jpeg_mgr: qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + cam_lrme_mgr: qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_qcs615"; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&pil_camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0c00 0x0>; + cam-smmu-label = "cpas-cdm"; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0de2 0x0>, + <&apps_smmu 0x0c80 0x0>, + <&apps_smmu 0x0ca0 0x0>, + <&apps_smmu 0x0d00 0x0>, + <&apps_smmu 0x0d20 0x0>; + cam-smmu-label = "icp"; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 8MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x800000>; + iova-region-id = <0x0>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.3 GB */ + iova-region-name = "io"; + iova-region-start = <0x10C00000>; + iova-region-len = <0xCF300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-qdss-region { + /* qdss region is approximately 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10B00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10A00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + iova-granularity = <0x15>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x40>, + <&apps_smmu 0x0840 0x00>, + <&apps_smmu 0x0860 0x40>; + cam-smmu-label = "ife"; + multiple-client-devices; + com,iommu-faults = "stall-disable", "non-fatal"; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0xd80 0x20>, + <&apps_smmu 0xda0 0x20>; + cam-smmu-label = "jpeg"; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0cc0 0x0>, + <&apps_smmu 0x0d40 0x0>; + cam-smmu-label = "lrme"; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "okay"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0xd800000>; + iova-region-len = <0xd2800000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; From a2d068f51e978d89e10121d852412249c257c18d Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:23:37 +0530 Subject: [PATCH 0584/1058] QCLINUX: arm64: dts: qcom: Change rb3gen2 camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index 37ea48e35d09c..2fadfb9de1fee 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -32,7 +32,7 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; src-clock-name = "soc_fast_ahb"; operating-points-v2 = <&a5_opp_table>; - fw_name = "CAMERA_ICP_170.elf"; + fw_name = "qcom/qcm6490/CAMERA_ICP_170.elf"; ubwc-ipe-fetch-cfg = <0x7073 0x707b>; ubwc-ipe-write-cfg = <0x161cf 0x161ef>; ubwc-bps-fetch-cfg = <0x7073 0x707b>; From 7cbc68db15065c85b3cda057d9cbc06190b78e84 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:33:18 +0530 Subject: [PATCH 0585/1058] QCLINUX: arm64: dts: qcom: Change monaco camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index f72161e75f7e7..258ad08ffee2f 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -1463,7 +1463,7 @@ <400000000 0 600000000 0>; clock-cntl-level = "svs_l1", "nominal"; nrt-device; - fw_name = "CAMERA_ICP"; + fw_name = "qcom/qcs8300/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; qos-val = <0xa0a>; From 010dc8f81f3357505b6963ef027aecec6546e4e2 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:32:20 +0530 Subject: [PATCH 0586/1058] QCLINUX: arm64: dts: qcom: Change lemans camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index 855d29dff618f..a207377cce6c1 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -1600,7 +1600,7 @@ <400000000 0 600000000 0>; clock-cntl-level = "svs_l1", "nominal"; nrt-device; - fw_name = "CAMERA_ICP"; + fw_name = "qcom/sa8775p/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; qos-val = <0xa0a>; From 30df39997353b26e70182f76d6262426ef69f733 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:30:22 +0530 Subject: [PATCH 0587/1058] QCLINUX: arm64: dts: qcom: Change talos camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index e2daa14db1e80..5a79115547f9a 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -43,7 +43,7 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; src-clock-name = "cam_cc_icp_clk_src"; operating-points-v2 = <&a5_opp_table>; - fw_name = "CAMERA_ICP.elf"; + fw_name = "qcom/qcs615/CAMERA_ICP.elf"; ubwc-cfg = <0x73 0x1CF>; cam_hw_pid = <15>; cell-index = <0>; From 75ea5c7eee5ed294eb9e976cf25ec5435e43a59e Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 9 Jan 2026 00:54:23 +0530 Subject: [PATCH 0588/1058] QCLINUX: arm64: dts: qcom: talos: add camnoc bandwidth levels Add two new AHB bandwidth levels for the camnoc path and update cam-ahb-num-cases accordingly. This ensures that the DT reflects the full set of supported interconnect bandwidth cases. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index 5a79115547f9a..e0f59fb00a5fc 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -134,9 +134,10 @@ "cam_hf_0_mnoc", "cam_hf_1_mnoc", "cam_sf_0_mnoc"; - cam-ahb-num-cases = <7>; + cam-ahb-num-cases = <9>; cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, - <0 300000>, <0 300000>, <0 300000>; + <0 300000>, <0 300000>, <0 300000>, + <0 300000>, <0 300000>; vdd-corners = Date: Fri, 23 Jan 2026 12:57:03 +0530 Subject: [PATCH 0589/1058] QCLINUX: arm64: dts: qcom: disabled vreg_cam1_2p8 regulator Disabled vreg_cam1_2p8 regulator to free GPIOs. Signed-off-by: Nihal Kumar Gupta Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso index 3945c77528ccb..c0fea4bb3dc23 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -105,3 +105,7 @@ }; }; }; + +&vreg_cam1_2p8 { + status = "disabled"; +}; From 94e5a0ecbb3b01a8a99f2c10d0ea1758dffb8192 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 29 Jan 2026 18:26:31 +0530 Subject: [PATCH 0590/1058] QCLINUX: arm64: dts: qcom: Enable IMX577 sensor on lemans Enable imx577 sensor on lemans boards from slot0 to slot3. Signed-off-by: Nihal Kumar Gupta --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 8eb1026e7da1b..2a650bc52d1fc 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -205,6 +205,47 @@ status = "ok"; }; + /*cam0-cmk_imx577*/ + qcom,cam-sensor27 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam27>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; + eeprom_cam24: qcom,eeprom24 { compatible = "qcom,eeprom"; cam_vio-supply = <&vreg_s4a>; @@ -239,6 +280,41 @@ cell-index = <24>; status = "ok"; }; + + eeprom_cam27: qcom,eeprom27 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; }; &cam_cci1 { @@ -401,6 +477,160 @@ cell-index = <21>; status = "ok"; }; + + /*cam1-imx577*/ + qcom,cam-sensor26 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam26>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <26>; + status = "ok"; + }; + + /*cam1-cmk_imx577*/ + qcom,cam-sensor28 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam28>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; + + eeprom_cam26: qcom,eeprom26 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <26>; + status = "ok"; + }; + + eeprom_cam28: qcom,eeprom28 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; }; &cam_cci2 { @@ -563,6 +793,83 @@ cell-index = <22>; status = "ok"; }; + + /*cam2-cmk_imx577*/ + qcom,cam-sensor29 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam29>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; + + eeprom_cam29: qcom,eeprom29 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; }; &cam_cci3 { @@ -725,6 +1032,83 @@ cell-index = <23>; status = "ok"; }; + + /*cam3-cmk_imx577*/ + qcom,cam-sensor30 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam30>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK3", + "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; + + eeprom_cam30: qcom,eeprom30 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; }; &soc { From 98dfaf21594dc1d0343b27c382f4739454a2e193 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 2 Feb 2026 15:46:31 +0530 Subject: [PATCH 0591/1058] QCLINUX: arm64: dts: qcom: Add camx overlay for talos evk Add camx overlay for talos EVK baord. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/talos-evk-camx.dtso | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9eacf8c4e60f7..a8c903830bd05 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -494,3 +494,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb + +talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" From fff8d3e66725c902cf18485339eca813da3d020b Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 2 Feb 2026 22:21:36 +0530 Subject: [PATCH 0592/1058] QCLINUX: arm64: dts: qcom: add node labels and explicit QoS flag in lemans Adds labels to cam-cpas and cam-icp nodes and changes enable-secure-qos-update from boolean to explicit. This change is required for KVM support. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index a207377cce6c1..d6cce86922c26 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -667,7 +667,7 @@ status = "ok"; }; - qcom,cam-cpas { + cam_cpas: qcom,cam-cpas { compatible = "qcom,cam-cpas"; label = "cpas"; arch-compat = "cpas_top"; @@ -743,7 +743,7 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; - enable-secure-qos-update; + enable-secure-qos-update = <1>; cell-index = <0>; status = "ok"; @@ -1114,7 +1114,7 @@ }; }; - qcom,cam-icp { + cam_icp_firmware: qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; From 8200178802276eb5ffa5dbac159bdd95f63e9cef Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 2 Feb 2026 22:38:12 +0530 Subject: [PATCH 0593/1058] QCLINUX: arm64: dts: qcom: add node labels and explicit QoS flag in monaco Adds labels to cam-cpas and cam-icp nodes and changes enable-secure-qos-update from boolean to explicit. This change is required for KVM support. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index 258ad08ffee2f..8250f66c34526 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -528,7 +528,7 @@ status = "ok"; }; - qcom,cam-cpas { + cam_cpas: qcom,cam-cpas { compatible = "qcom,cam-cpas"; label = "cpas"; arch-compat = "cpas_top"; @@ -605,7 +605,7 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg13", "tpg14", "tpg15"; - enable-secure-qos-update; + enable-secure-qos-update = <1>; cell-index = <0>; status = "ok"; @@ -976,7 +976,7 @@ }; }; - qcom,cam-icp { + cam_icp_firmware: qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; From 5dad42885641d56d4bbdb0b9437727f9320314fc Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Sat, 7 Feb 2026 15:37:33 +0530 Subject: [PATCH 0594/1058] QCLINUX: arm64: dts: qcom: lemans: Add CamX EL2 overlay Add camx el2 DT overlay for lemans platforms. The overlay updates the ICP firmware node with Secure SMMU SID and disables secure QoS updates for CPAS in EL2/KVM configurations. Wire up the new overlay-built DTBs in the qcom DT Makefile so the corresponding *-camx-el2.dtb targets are generated. Co-developed-by: Ignatius Michael Jihan Signed-off-by: Ignatius Michael Jihan Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a8c903830bd05..a8e7d0769a64b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -462,6 +462,10 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso new file mode 100644 index 0000000000000..83b5605f026a8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + /* cam_cpas label -> /soc@0/qcom,cam-cpas * + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + /* cam_icp_firmware label -> /soc@0/qcom,cam-icp */ + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; From e309d5879336d2848e6c8a0ae5710666c2737255 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Mon, 2 Mar 2026 16:36:16 +0530 Subject: [PATCH 0595/1058] QCLINUX: arm64: dts: qcom: add labels to sensor DTSI Add DT labels to sensor nodes in the Lemans and Kodiak DTSI files to enable phandle references. Monaco changes are already handled. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi | 8 ++++---- .../boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 2a650bc52d1fc..e1ee2ba8c78e6 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb8_slot0: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -439,7 +439,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor21 { + rb8_slot1: qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -755,7 +755,7 @@ }; /*cam2-ov9282*/ - qcom,cam-sensor22 { + rb8_slot2: qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -994,7 +994,7 @@ }; /*cam3-ov9282*/ - qcom,cam-sensor23 { + rb8_slot3: qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi index 8b75b1a441db4..026b97b58377d 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -55,7 +55,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb3_slot0a: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; cell-index = <1>; csiphy-sd-index = <0>; @@ -92,7 +92,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor6 { + rb3_slot1: qcom,cam-sensor6 { compatible = "qcom,cam-sensor"; cell-index = <6>; csiphy-sd-index = <1>; @@ -254,7 +254,7 @@ }; /*cam3-imx577*/ - qcom,cam-sensor0 { + rb3_slot3: qcom,cam-sensor0 { compatible = "qcom,cam-sensor"; cell-index = <0>; csiphy-sd-index = <3>; @@ -345,7 +345,7 @@ }; /*cam0b-ov9282*/ - qcom,cam-sensor7 { + rb3_slot0b: qcom,cam-sensor7 { compatible = "qcom,cam-sensor"; cell-index = <7>; csiphy-sd-index = <0>; @@ -383,7 +383,7 @@ }; /*cam2-imx577*/ - qcom,cam-sensor8 { + rb3_slot2: qcom,cam-sensor8 { compatible = "qcom,cam-sensor"; cell-index = <8>; csiphy-sd-index = <2>; From 38063a31bf08b27adaf1ef54239e8d0754ee4bb6 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 13 Mar 2026 14:59:50 +0530 Subject: [PATCH 0596/1058] QCLINUX: arm64: dts: qcom: lemans: Fix comment typo in camx EL2 dtso. Fix a typo in the camx EL2 device tree by removing comments all together. The mistake was masked by a later comment terminator. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso index 83b5605f026a8..c7ddbc01a0070 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso @@ -7,7 +7,6 @@ /plugin/; / { - /* cam_cpas label -> /soc@0/qcom,cam-cpas * fragment@0 { target-path = "/soc@0/qcom,cam-cpas"; __overlay__ { @@ -15,7 +14,6 @@ }; }; - /* cam_icp_firmware label -> /soc@0/qcom,cam-icp */ fragment@1 { target-path = "/soc@0/qcom,cam-icp"; __overlay__ { From 49a90841167baa35832374827404ac1d3fe403a9 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 13 Mar 2026 19:24:42 +0530 Subject: [PATCH 0597/1058] QCLINUX: arm64: dts: qcom: monaco: Add CamX EL2 overlay Add camx el2 DT overlay for lemans platforms. The overlay updates the ICP firmware node with Secure SMMU SID and disables secure QoS updates for CPAS in EL2/KVM configurations. Wire up the new overlay-built DTBs in the qcom DT Makefile so the corresponding *-camx-el2.dtb targets are generated. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a8e7d0769a64b..fb683c4667569 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -470,6 +470,10 @@ monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso new file mode 100644 index 0000000000000..c7ddbc01a0070 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; From cb35cc4731887ffc9e976a369d1ffccc398311af Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Tue, 7 Apr 2026 11:07:43 +0530 Subject: [PATCH 0598/1058] QCLINUX: arm64: dts: qcom: Add Hamoa camx overlay dts Add CAMX overlay dts file for Hamoa boards. This change also enables the compilation of the CAMX overlay for Hamoa boards. Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../boot/dts/qcom/hamoa-camera-camx.dtso | 26 + .../boot/dts/qcom/hamoa-camera-sensor.dtsi | 53 + arch/arm64/boot/dts/qcom/hamoa-camera.dtsi | 2473 +++++++++++++++++ 4 files changed, 2556 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index fb683c4667569..2b651b7b715a0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -458,6 +458,10 @@ dtb-$(CONFIG_ARCH_QCOM) += x1p42100-lenovo-thinkbook-16.dtb x1p42100-lenovo-thin x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb +hamoa-camera-dtbs := hamoa-iot-evk.dtb hamoa-camera-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camera-camx.dtb + lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso new file mode 100644 index 0000000000000..d63daf990f2a1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hamoa-camera.dtsi" +#include "hamoa-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi new file mode 100644 index 0000000000000..7ebfcf1ec3912 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /*cam0-cmk_imx577*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 97 0>, + <&tlmm 110 0>, + <&tlmm 19 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi new file mode 100644 index 0000000000000..94dd42b380f4e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi @@ -0,0 +1,2473 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1e80100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", "sfe0", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + sfe0_all_rd: sfe0-all-rd { + cell-index = <24>; + node-name = "sfe0-all-rd"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_rt0_rd>; + }; + + sfe0_rdi_stats_nrdi_wr: sfe0-rdi-stats-nrdi-wr { + cell-index = <25>; + node-name = "sfe0-rdi-stats-nrdi-wr"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <26>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <27>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <28>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <29>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <30>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <31>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <32>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <33>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <34>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <35>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <36>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <37>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <38>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <39>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <41>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <42>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe0: qcom,sfe0@ac9e000 { + compatible = "qcom,sfe680"; + reg = <0x0 0xac9e000 0x0 0x8000>; + reg-names = "sfe0"; + reg-cam-base = <0x9e000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "sfe"; + power-domains = <&camcc CAM_CC_SFE_0_GDSC>; + clocks = <&camcc CAM_CC_SFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_0_CLK_SRC>, + <&camcc CAM_CC_SFE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_0_CLK>; + clock-names = "sfe_0_fast_ahb", + "sfe_0_clk_src", + "sfe_0_clk", + "cam_cc_cpas_sfe_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "sfe_0_clk_src"; + operating-points-v2 = <&sfe0_opp_table>; + cam_hw_pid = <10 2>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + sfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@ace8000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy2_opp_table>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; From 3b5e15b68ef2d762206f30770369b2c6564ffb10 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Tue, 7 Apr 2026 16:37:49 +0530 Subject: [PATCH 0599/1058] QCLINUX: arm64: dts: qcom: align hamoa camera DTB variable naming Rename the hamoa camera DTBs variable to match the hamoa-camera-camx DTB target naming and improve consistency with existing Makefile conventions. Fixes: 9041882f7c4c ("QCLINUX: arm64: dts: qcom: Add hamoa camx overlay dts") Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++-- .../dts/qcom/{hamoa-camera-camx.dtso => hamoa-evk-camx.dtso} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename arch/arm64/boot/dts/qcom/{hamoa-camera-camx.dtso => hamoa-evk-camx.dtso} (100%) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 2b651b7b715a0..9a23ad124f82a 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -458,9 +458,9 @@ dtb-$(CONFIG_ARCH_QCOM) += x1p42100-lenovo-thinkbook-16.dtb x1p42100-lenovo-thin x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb -hamoa-camera-dtbs := hamoa-iot-evk.dtb hamoa-camera-camx.dtbo +hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo -dtb-$(CONFIG_ARCH_QCOM) += hamoa-camera-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso similarity index 100% rename from arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso rename to arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso From 7db89373ebc024c9719c433094d58c0a1d948780 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:13:12 +0530 Subject: [PATCH 0600/1058] PENDING: arm64: dts: qcom: lemans-evk: add overlay for QPS615 ethernet Add an overlay devicetree for Lemans EVK for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/lemans-evk-staging.dtso | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9a23ad124f82a..6e296f5211827 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -470,6 +470,8 @@ lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2. dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso new file mode 100644 index 0000000000000..cf345ec5d06c9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&i2c18 { + eeprom@52 { + nvmem-layout { + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + mac_addr3: mac-addr@c { + reg = <0xc 0x6>; + }; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 56 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 57 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr3>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio56"; + function = "gpio"; + input-enable; + bias-disable; + }; + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio57"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From 9e46e8e72b53c9af1b14b084aa8933dfe4e0bd50 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:19:46 +0530 Subject: [PATCH 0601/1058] PENDING: arm64: dts: qcom: monaco-evk: add overlay for QPS615 ethernet Add an overlay devicetree for Monaco EVK for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/monaco-evk-staging.dtso | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6e296f5211827..e2c879a6837f9 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -480,6 +480,8 @@ monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2. dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso new file mode 100644 index 0000000000000..a646b28f6f9d0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&eeprom1 { + nvmem-layout { + mac_addr1: mac-addr@0 { + reg = <0x0 0x6>; + }; + + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 40 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr1>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 39 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&expander5 0 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio40"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio39"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From 95639c245e0745680a034f2be433b94fa7cf3d04 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:24:07 +0530 Subject: [PATCH 0602/1058] PENDING: arm64: dts: qcom: rb3gen2: add overlay for QPS615 ethernet Add an overlay devicetree for Rb3Gen2 for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../dts/qcom/qcs6490-rb3gen2-staging.dtso | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e2c879a6837f9..29efe4f74dd39 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -491,6 +491,8 @@ qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.d dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo + qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso new file mode 100644 index 0000000000000..79f9c055c9776 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +/ { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + gpio = <&pm7325_gpios 8 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + gpio = <&pm7250b_gpios 4 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + /* + * PF0: also acts as the QPS615 GPIO controller. + * gpio-controller / #gpio-cells expose the TC956X + * internal GPIO lines (hardware numbers 0-13) so that + * phy-reset-gpios can reference them. + */ + qps615: pci@0,0 { + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&aqr_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&qep_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + mux { + pins = "gpio141"; + function = "gpio"; + }; + + config { + pins = "gpio141"; + input-enable; + bias-disable; + }; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + mux { + pins = "gpio101"; + function = "gpio"; + }; + + config { + pins = "gpio101"; + input-enable; + bias-disable; + }; + }; + }; +}; From b9f5067ae07a956ac12c1572aafbdc079bd216a6 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 13 Apr 2026 09:41:19 +0530 Subject: [PATCH 0603/1058] PEDNING: arm64: dts: qcom: qcs6490-rb3gen2: fix root node overlay for phy-vreg The staging overlay used a bare "/ {" root node block to define the qep_vreg and aqr_vreg fixed regulators. In a DT overlay, a bare "/ {" creates a new root fragment that is not merged into the base tree's root node; as a result the regulator nodes are never instantiated and the tc956x driver cannot resolve the phy-supply phandle, leading to a failed MDIO probe: tc956x_pci-eth 0001:05:00.1: No PHY found Replace "/ {" with the overlay-correct "&{/} {" syntax so that the fragment is properly applied as an amendment to the base device-tree root node. This ensures the regulator nodes are present at boot and the PHY powers up correctly. Fixes: 00ba37e0f45d ("PENDING: arm64: dts: qcom: rb3gen2: add overlay for QPS615 ethernet") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso index 79f9c055c9776..6c112224f0ce9 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso @@ -9,7 +9,7 @@ #include #include -/ { +&{/} { qep_vreg: qep_vreg { compatible = "regulator-fixed"; regulator-name = "qep_vreg"; From 966a7c7b661b97e5596e39db4436e35b5cb9b61f Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 8 Apr 2026 16:36:42 +0800 Subject: [PATCH 0604/1058] PENDING: arm64: qcom: dts: talos: add TGU device in staging dtso Add TGU device for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/talos-staging.dtso | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 29efe4f74dd39..9fbd74e34db0e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -516,3 +516,5 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb + +dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/talos-staging.dtso b/arch/arm64/boot/dts/qcom/talos-staging.dtso new file mode 100644 index 0000000000000..04602073418d4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Talos staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0c000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From d7ca6ec26244a3c72657c81dbe059552bc007d0f Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 14:46:05 +0800 Subject: [PATCH 0605/1058] PENDING: arm64: dts: qcom: lemans: add TGU device in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/lemans-staging.dtso | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9fbd74e34db0e..bdb13e6002bf1 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -472,6 +472,8 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-staging.dtso new file mode 100644 index 0000000000000..ad919bfb6b19a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Lemans staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 26c3737b92cf2b6bd3bbcb124cc3422559dcca8e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 14:59:42 +0800 Subject: [PATCH 0606/1058] PENDING: arm64: dts: qcom: monaco: add TGU device in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/monaco-staging.dtso | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index bdb13e6002bf1..1d3fc3a47934d 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -484,6 +484,8 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-staging.dtso new file mode 100644 index 0000000000000..fc44741b8caab --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Monaco staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From b93c13749964c04e5001887f810847b58635ef7d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 15:11:57 +0800 Subject: [PATCH 0607/1058] PENDING: arm64: dts: qcom: kodiak: add TGU device in staging dtso Add TGU device for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/kodiak-staging.dtso | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kodiak-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1d3fc3a47934d..331a17c5858bf 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -522,3 +522,5 @@ talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/kodiak-staging.dtso b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso new file mode 100644 index 0000000000000..1d4c6d7d39dd0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 570c1e59b04235a895d30b6cf048263a0d054660 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 22 Apr 2026 16:49:21 +0530 Subject: [PATCH 0608/1058] QCLINUX: arm64: dts: qcom: talos-evk: Switch to interrupt-cells 4 Update Talos EVK camera DT nodes to use 4-cell interrupt specifiers, aligning with upstream Talos GIC changes required for PPI interrupt partitioning. This Change is required to remain compliant with the updated GIC binding, even for SPI-based camera interrupts. Link: https://lore.kernel.org/all/20260108092542.1371-2-yuanjie.yang@oss.qualcomm.com/ Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index e0f59fb00a5fc..7d6f1268fa396 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -15,7 +15,7 @@ <0x0 0xac18000 0x0 0x3000>; reg-names = "icp_qgic", "icp_sierra", "icp_csr"; reg-cam-base = <0x00000 0x10000 0x18000>; - interrupts = ; + interrupts = ; interrupt-names = "a5"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -92,7 +92,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "cam_cpas_top", "cam_camnoc"; reg-cam-base = <0x40000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "cpas_camnoc"; camnoc-axi-min-ib-bw = <3000000000>; power-domains = <&camcc TITAN_TOP_GDSC>; @@ -505,7 +505,7 @@ reg = <0x0 0xac48000 0x0 0x1000>; reg-names = "cpas-cdm"; reg-cam-base = <0x48000>; - interrupts = ; + interrupts = ; interrupt-names = "cpas-cdm"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -545,7 +545,7 @@ reg = <0x0 0xac4a000 0x0 0x4000>; reg-names = "cci"; reg-cam-base = <0x4a000>; - interrupts = ; + interrupts = ; interrupt-names = "CCI"; operating-points-v2 = <&cci_opp_table>; power-domains = <&camcc TITAN_TOP_GDSC>; @@ -642,7 +642,7 @@ reg = <0x0 0xac4e000 0x0 0x4000>; reg-names = "jpege_hw"; reg-cam-base = <0x4e000>; - interrupts = ; + interrupts = ; interrupt-names = "jpeg"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -681,7 +681,7 @@ reg = <0x0 0xac52000 0x0 0x4000>; reg-names = "jpegdma_hw"; reg-cam-base = <0x52000>; - interrupts = ; + interrupts = ; interrupt-names = "jpegdma"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -721,7 +721,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy0_opp_table>; reg-cam-base = <0x65000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY0"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -770,7 +770,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy1_opp_table>; reg-cam-base = <0x66000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY1"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -819,7 +819,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy2_opp_table>; reg-cam-base = <0x67000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY2"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -867,7 +867,7 @@ reg = <0x0 0xac6b000 0x0 0xa00>; reg-names = "lrme"; reg-cam-base = <0x6b000>; - interrupts = ; + interrupts = ; interrupt-names = "lrme"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1056,7 +1056,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "ife0", "cam_camnoc"; reg-cam-base = <0xaf000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "ife0"; power-domains = <&camcc IFE_0_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1128,7 +1128,7 @@ reg = <0x0 0xacb3000 0x0 0x1000>; reg-names = "csid0"; reg-cam-base = <0xb3000>; - interrupts = ; + interrupts = ; interrupt-names = "csid0"; power-domains = <&camcc IFE_0_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1211,7 +1211,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "ife1", "cam_camnoc"; reg-cam-base = <0xb6000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "ife1"; power-domains = <&camcc IFE_1_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1283,7 +1283,7 @@ reg = <0x0 0xacba000 0x0 0x1000>; reg-names = "csid1"; reg-cam-base = <0xba000>; - interrupts = ; + interrupts = ; interrupt-names = "csid1"; power-domains = <&camcc IFE_1_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1365,7 +1365,7 @@ reg = <0x0 0xacc4000 0x0 0x4000>; reg-names = "ife-lite0"; reg-cam-base = <0xc4000>; - interrupts = ; + interrupts = ; interrupt-names = "ife-lite0"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1432,7 +1432,7 @@ reg = <0x0 0xacc8000 0x0 0x1000>; reg-names = "csid-lite0"; reg-cam-base = <0xc8000>; - interrupts = ; + interrupts = ; interrupt-names = "csid-lite0"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, From 8a6d8e37fa94d128cd5d5078217d9a6e60f411ed Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Sun, 19 Apr 2026 20:35:15 +0530 Subject: [PATCH 0609/1058] PENDING: arm64: dts: qcom: rb3gen2-industrial-mezzanine: add overlay for QPS615 Add an overlay devicetree to enable Rb3Gen2 industrial board's 4 ethernet ports provided by two QPS615 PCIe Ethernet switches. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + ...-rb3gen2-industrial-mezzanine-staging.dtso | 119 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 331a17c5858bf..bb086f62bbda3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -497,6 +497,8 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-staging.dtbo + qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso new file mode 100644 index 0000000000000..edb284558b5a6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7325_gpios 8 0>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7250b_gpios 4 0>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + qps615: pci@0,0 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + phy-supply = <&aqr_vreg>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&pcie0_port { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 136 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&rtl_rc0_intn_wol_sig>; + phy-mode = "sgmii"; + phy-reset-gpios = <&tlmm 90 GPIO_ACTIVE_LOW>; + reset-deassert-us = <75000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 142 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_rc0_intn_wol_sig>; + phy-reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + pins = "gpio141"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + pins = "gpio101"; + function = "gpio"; + input-enable; + bias-disable; + }; + + rtl_rc0_intn_wol_sig: rtl_rc0_intn_wol_sig { + pins = "gpio136"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_rc0_intn_wol_sig: napa_rc0_intn_wol_sig { + pins = "gpio142"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From e87ba72c04ae37d9effdf51af256f92b7496147d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 28 Apr 2026 14:50:22 +0800 Subject: [PATCH 0610/1058] PENDING: arm64: dts: qcom: glymur: add TGU and ETR in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file and add ETR devices for supporting DDR memory trace. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + arch/arm64/boot/dts/qcom/glymur-staging.dtso | 201 +++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index bb086f62bbda3..3683b99a923b0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -526,3 +526,5 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/glymur-staging.dtso b/arch/arm64/boot/dts/qcom/glymur-staging.dtso new file mode 100644 index 0000000000000..0b95e568e1c00 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-staging.dtso @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Glymur staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + ctcu@10001000 { + compatible = "qcom,glymur-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x00e0 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0100 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + + tgu@11c02000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c02000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + replicator@11c06000 { + out-ports { + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + }; + }; + + tgu@11c0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From e2a60a44867159654a9b2bb124f7407714690071 Mon Sep 17 00:00:00 2001 From: Vishwas Udupa Date: Fri, 3 Apr 2026 02:17:06 -0700 Subject: [PATCH 0611/1058] FROMLIST: arm64: dts: qcom: install DT overlays via dtbs_install Overlay binaries (.dtbo) are currently only built implicitly as dependencies of composite firmware images and are therefore absent from the kernel install output. Even when final DTBs are produced at build time, some distributions rely on standalone DTBOs for runtime selection and application by bootloaders or firmware. Without explicit install targets, DTBOs are not picked up by the standard dtbs_install flow and therefore cannot be packaged alongside DTBs. Add explicit dtb-$(CONFIG_ARCH_QCOM) entries for all DT overlays defined in this Makefile so they are installed via dtbs_install, matching existing DTB install behaviour. Link: https://lore.kernel.org/all/20260428123725.3457865-1-vudupa@qti.qualcomm.com Signed-off-by: Vishwas Udupa --- arch/arm64/boot/dts/qcom/Makefile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 3683b99a923b0..2f214da6fc68a 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -7,7 +7,9 @@ apq8016-sbc-usb-host-dtbs := apq8016-sbc.dtb apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += sar2130p-qar2130p.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-schneider-hmibsc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb @@ -48,13 +50,16 @@ lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx5 lemans-evk-camera-dtbs := lemans-evk.dtb lemans-evk-camera.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtbo lemans-evk-el2-dtbs := lemans-evk.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-el2.dtb lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb @@ -63,12 +68,14 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb monaco-evk-camera-imx577-dtbs := monaco-evk.dtb monaco-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtbo monaco-evk-el2-dtbs := monaco-evk.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-el2.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb @@ -174,6 +181,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride.dtb qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb @@ -181,7 +189,9 @@ qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vis qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb @@ -189,6 +199,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb qcs8300-ride-el2-dtbs := qcs8300-ride.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb @@ -198,6 +209,7 @@ qcs9100-ride-r3-el2-dtbs := qcs9100-ride-r3.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-arduino-imola.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb @@ -205,6 +217,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine-dtbs := qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb @@ -212,6 +225,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine-dtbs := qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qru1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb @@ -222,6 +236,7 @@ sc7180-acer-aspire1-el2-dtbs := sc7180-acer-aspire1.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb sc7180-acer-aspire1-el2.dtb sc7180-ecs-liva-qc710-el2-dtbs := sc7180-ecs-liva-qc710.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-ecs-liva-qc710.dtb sc7180-ecs-liva-qc710-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.dtb @@ -297,6 +312,7 @@ sc8280xp-microsoft-arcata-el2-dtbs := sc8280xp-microsoft-arcata.dtb sc8280xp-el2 dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-arcata.dtb sc8280xp-microsoft-arcata-el2.dtb sc8280xp-microsoft-blackrock-el2-dtbs := sc8280xp-microsoft-blackrock.dtb sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-blackrock.dtb sc8280xp-microsoft-blackrock-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-lenovo-tbx605f.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-motorola-ali.dtb @@ -315,6 +331,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine-dtbs := sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-crosshatch.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-blueline.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyln.dtb @@ -380,7 +397,9 @@ sm8550-hdk-rear-camera-card-dtbs := sm8550-hdk.dtb sm8550-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-qrd.dtb @@ -394,7 +413,9 @@ sm8650-hdk-rear-camera-card-dtbs := sm8650-hdk.dtb sm8650-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb @@ -403,12 +424,14 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8750-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-evk.dtb talos-evk-usb1-peripheral-dtbs := talos-evk.dtb talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtbo talos-evk-camera-imx577-dtbs := talos-evk.dtb talos-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtb talos-evk-lvds-auo,g133han01-dtbs := \ talos-evk.dtb talos-evk-lvds-auo,g133han01.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtbo x1e001de-devkit-el2-dtbs := x1e001de-devkit.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1e001de-devkit.dtb x1e001de-devkit-el2.dtb x1e78100-lenovo-thinkpad-t14s-el2-dtbs := x1e78100-lenovo-thinkpad-t14s.dtb x1-el2.dtbo @@ -457,6 +480,7 @@ x1p42100-lenovo-thinkbook-16-el2-dtbs := x1p42100-lenovo-thinkbook-16.dtb x1-el2 dtb-$(CONFIG_ARCH_QCOM) += x1p42100-lenovo-thinkbook-16.dtb x1p42100-lenovo-thinkbook-16-el2.dtb x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo From 197740e3398d85242950137a51ee14b1b52466bb Mon Sep 17 00:00:00 2001 From: Vishwas Udupa Date: Thu, 30 Apr 2026 03:53:25 -0700 Subject: [PATCH 0612/1058] QCLINUX: arm64: dts: qcom: Install camx DTBO overlays Install Qualcomm camx DTBO overlay files by adding them to the dtb-$(CONFIG_ARCH_QCOM) build/install list This makes DTBOs available through the standard dtbs_install flow and ensures they are included in distro kernel packages Signed-off-by: Vishwas Udupa --- arch/arm64/boot/dts/qcom/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 2f214da6fc68a..e2e1d06544632 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -485,14 +485,17 @@ dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtbo lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo @@ -501,10 +504,12 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtbo monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo @@ -513,11 +518,13 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo @@ -526,6 +533,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-staging.dtbo qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtbo qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo @@ -538,6 +546,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtbo sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo @@ -546,6 +555,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo From 468d03c73e5c2b59f18ef4e6758577eebb860609 Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0613/1058] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ .../arm64/boot/dts/qcom/qcs5430-fps-camx.dtso | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e2e1d06544632..896ec1baea1fa 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -520,6 +520,10 @@ qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo +qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso new file mode 100644 index 0000000000000..4255147f00ef9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* +* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +*/ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&cam_csid2 { + status = "disabled"; +}; + +&cam_vfe2 { + status = "disabled"; +}; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; From 68e67f963aa378bdd8381fe4039cbc795a7337ac Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0614/1058] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 896ec1baea1fa..2403dda997d14 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -515,6 +515,10 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo +qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb From fff27725fd1064e09f0c5362e8d7800204584342 Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0615/1058] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 2403dda997d14..dcb5f544dfd14 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -524,10 +524,6 @@ qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo -qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb - qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo From 1e04f85d80cff0db425be2efcd5f7bc629abf6df Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 22 Apr 2026 20:32:50 +0530 Subject: [PATCH 0616/1058] QCLINUX: arm64: dts: qcom: Add Purwa camx overlay dts Add CAMX overlay dts file for purwa boards. This change also enables the compilation of the CAMX overlay for purwa boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 4 + arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 2056 ++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 25 + 3 files changed, 2085 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index dcb5f544dfd14..26a93f0260610 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -515,6 +515,10 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo +purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb + qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi new file mode 100644 index 0000000000000..5896e5759e22f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -0,0 +1,2056 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1p4x100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy4", "cci0", "cci1", "csid0", + "csid1", "csid2", "ife0", "ife1", "ife2", "ipe0", + "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", + "cam-cdm-intf0", "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "tpg13", "tpg14", "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <7>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <8>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <9>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <10>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <11>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <12>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <13>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <14>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <15>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <16>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <17>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <18>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <19>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <20>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <21>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <22>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <23>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <24>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <25>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <26>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <27>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <28>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <29>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <1>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <2>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso new file mode 100644 index 0000000000000..26603aed4eafc --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "purwa-camera.dtsi" + +&camss { + status = "disabled"; +}; From 4e36e09e03a6b38f4165830dd25856969adf903e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:14:20 +0800 Subject: [PATCH 0617/1058] PENDING: arm64: dts: qcom: hamoa: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 35 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 26a93f0260610..a9fd7d5375af3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -570,3 +570,5 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso new file mode 100644 index 0000000000000..feb3c7c5ccd82 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Hamoa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 8fba4e1f73c7a76d82511fcfdd4bd5dbc4aec07a Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:18:09 +0800 Subject: [PATCH 0618/1058] PENDING: arm64: dts: qcom: sm8750: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/sm8750-staging.dtso | 35 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8750-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a9fd7d5375af3..0bcf51f87ab53 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -572,3 +572,5 @@ dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/sm8750-staging.dtso b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso new file mode 100644 index 0000000000000..68c477c63a328 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SM8750 staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 455e24ee4bd83c4678dafbe093af22420080feaf Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:21:04 +0800 Subject: [PATCH 0619/1058] PENDING: arm64: dts: qcom: kaanapali: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/kaanapali-staging.dtso | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kaanapali-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 0bcf51f87ab53..cc05b48820624 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -574,3 +574,5 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso new file mode 100644 index 0000000000000..d7a5b0b084872 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kaanapali staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@11301000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11301000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@1130e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@1130f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11310000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11310000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 6c255c69d2f7721e768a5de2a010e2842253eb8d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 15:26:51 +0800 Subject: [PATCH 0620/1058] PENDING: arm64: dts: qcom: glymur: add Coresight devices for APSS debug block Add the following devices that are part of the APSS debug block to enable debug features, including ETM, replicator, funnel, and TMC ETF. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/glymur-staging.dtso | 1248 ++++++++++++++++++ 1 file changed, 1248 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-staging.dtso b/arch/arm64/boot/dts/qcom/glymur-staging.dtso index 0b95e568e1c00..eb928fca1a371 100644 --- a/arch/arm64/boot/dts/qcom/glymur-staging.dtso +++ b/arch/arm64/boot/dts/qcom/glymur-staging.dtso @@ -8,6 +8,315 @@ /dts-v1/; /plugin/; +&{/} { + ete-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + ete-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + ete-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + ete-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + ete-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + ete-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + ete-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + ete-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + ete-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + ete-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + ete-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc1_4_rep_in>; + }; + }; + }; + }; + + ete-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc1_5_rep_in>; + }; + }; + }; + }; + + ete-12 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu12>; + qcom,skip-power-up; + + out-ports { + port { + etm12_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + ete-13 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu13>; + qcom,skip-power-up; + + out-ports { + port { + etm13_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + ete-14 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu14>; + qcom,skip-power-up; + + out-ports { + port { + etm14_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + ete-15 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu15>; + qcom,skip-power-up; + + out-ports { + port { + etm15_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + + ete-16 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu16>; + qcom,skip-power-up; + + out-ports { + port { + etm16_out: endpoint { + remote-endpoint = <&ncc2_4_rep_in>; + }; + }; + }; + }; + + ete-17 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu17>; + qcom,skip-power-up; + + out-ports { + port { + etm17_out: endpoint { + remote-endpoint = <&ncc2_5_rep_in>; + }; + }; + }; + }; + +}; + &soc { ctcu@10001000 { compatible = "qcom,glymur-ctcu", "qcom,sa8775p-ctcu"; @@ -155,6 +464,21 @@ }; }; + tn@11200000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; + tgu@11c02000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x11c02000 0x0 0x1000>; @@ -198,4 +522,928 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + + funnel@1d021000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d090000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc1_1_funnel_in4: endpoint { + remote-endpoint = <&ncc1_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc1_1_funnel_in5: endpoint { + remote-endpoint = <&ncc1_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d1b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d1c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; + + out-ports { + port { + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d1d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_4_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; + + out-ports { + port { + ncc1_4_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d1e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_5_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; + + out-ports { + port { + ncc1_5_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d221000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d221000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; + }; + }; + }; + }; + + tmc@1d229000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d229000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; + }; + }; + }; + }; + + funnel@1d281000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d281000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc2_1_funnel_in4: endpoint { + remote-endpoint = <&ncc2_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc2_1_funnel_in5: endpoint { + remote-endpoint = <&ncc2_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d290000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d290000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm12_out>; + }; + }; + }; + + out-ports { + port { + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d2a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm13_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d2b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm14_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d2c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm15_out>; + }; + }; + }; + + out-ports { + port { + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d2d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_4_rep_in: endpoint { + remote-endpoint = <&etm16_out>; + }; + }; + }; + + out-ports { + port { + ncc2_4_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d2e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_5_rep_in: endpoint { + remote-endpoint = <&etm17_out>; + }; + }; + }; + + out-ports { + port { + ncc2_5_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in5>; + }; + }; + }; + }; }; From 997000ff3d1ec168aa218e1b309c6086080c6554 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 15 May 2026 19:02:44 +0530 Subject: [PATCH 0621/1058] arm64: dts: qcom: hamoa: add CAMX EL2 overlay Add a device tree overlay to enable EL2 boot support for the Hamoa platform with CAMX configuration. CRs-Fixed: 4538425 Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index cc05b48820624..8039ae1ea8dba 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -487,6 +487,10 @@ hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo +hamoa-camx-el2-dtbs := hamoa-iot-evk-el2.dtb hamoa-evk-camx.dtbo hamoa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camx-el2.dtb + lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; From 1014efd825f2a1faa764f47ca4529a1ee1b7649d Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 22 May 2026 17:01:49 +0530 Subject: [PATCH 0622/1058] QCLINUX: arm64: dts: qcom: add Purwa CAMX EL2 overlay Add a device tree overlay to enable EL2 boot support for the Purwa platform with CAMX configuration. CRs-Fixed: 4546991 Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 8039ae1ea8dba..b0353dabaac49 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -523,6 +523,10 @@ purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb +purwa-camx-el2-dtbs := purwa-iot-evk-el2.dtb purwa-evk-camx.dtbo purwa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-camx-el2.dtb + qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; From 0bc4a0161b7fb2546caf15d98a5c069f893ead09 Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Thu, 21 May 2026 14:32:48 +0530 Subject: [PATCH 0623/1058] QCLINUX: arm64: dts: qcom: Enable combo mode for CSI1 port In order to enable combo mode on CSI1 mode, resources needs to be in shared mode. This change adds required resources under res-mgr node. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 77 +++++-------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index e1ee2ba8c78e6..959e2690848ff 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - rb8_slot0: qcom,cam-sensor1 { + qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -439,7 +439,7 @@ }; /*cam1-ov9282*/ - rb8_slot1: qcom,cam-sensor21 { + qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -454,10 +454,8 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; + pinctrl-0 = <&cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_suspend_rst1>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, @@ -478,14 +476,14 @@ status = "ok"; }; - /*cam1-imx577*/ - qcom,cam-sensor26 { + /*cam1-cmk_imx577*/ + qcom,cam-sensor28 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; - eeprom-src = <&eeprom_cam26>; + eeprom-src = <&eeprom_cam28>; cam_vio-supply = <&vreg_s4a>; regulator-names = "cam_vio"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; @@ -515,18 +513,17 @@ clock-names = "cam_clk"; clock-cntl-level = "nominal"; clock-rates = <24000000>; - cell-index = <26>; + cell-index = <28>; status = "ok"; }; - /*cam1-cmk_imx577*/ - qcom,cam-sensor28 { + /*cam1-ov9282*/ + qcom,cam-sensor31 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; - eeprom-src = <&eeprom_cam28>; cam_vio-supply = <&vreg_s4a>; regulator-names = "cam_vio"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; @@ -536,13 +533,8 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, - <&tlmm 133 0>, + <&expander2 2 0>, <&pmm8654au_0_gpios 8 0>; gpio-reset = <1>; gpio-custom1 = <2>; @@ -556,43 +548,7 @@ clock-names = "cam_clk"; clock-cntl-level = "nominal"; clock-rates = <24000000>; - cell-index = <28>; - status = "ok"; - }; - - eeprom_cam26: qcom,eeprom26 { - compatible = "qcom,eeprom"; - cam_vio-supply = <&vreg_s4a>; - regulator-names = "cam_vio"; - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; - rgltr-load-current = <120000>; - gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 73 0>, - <&tlmm 133 0>, - <&pmm8654au_0_gpios 8 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1", - "CAM_CUSTOM1"; - sensor-mode = <0>; - cci-master = <0>; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "nominal"; - clock-rates = <24000000>; - cell-index = <26>; + cell-index = <31>; status = "ok"; }; @@ -755,7 +711,7 @@ }; /*cam2-ov9282*/ - rb8_slot2: qcom,cam-sensor22 { + qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -994,7 +950,7 @@ }; /*cam3-ov9282*/ - rb8_slot3: qcom,cam-sensor23 { + qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; @@ -1115,6 +1071,11 @@ qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; gpios-shared = <518 519 520 521>; + gpios-shared-pinctrl = <633>; + shared-pctrl-gpio-names = "mclk1"; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "mclk1_active", "mclk1_suspend"; status = "ok"; }; }; From ea11453e6a4432777122d6ae3dd1e47950844d16 Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Mon, 25 May 2026 20:03:32 +0530 Subject: [PATCH 0624/1058] QCLINUX: arm64: dts: qcom: Fix GPIO free and acquire logic Prevent GPIOs managed by pinctrl from being requested and freed via the GPIO framework. Restrict GPIO request/free operations to non-pinctrl GPIOs by adding appropriate conditions. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 266 +++++++----------- 1 file changed, 105 insertions(+), 161 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 959e2690848ff..f7005902a98a2 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb8_slot0: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -140,20 +140,16 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; @@ -181,21 +177,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -222,21 +214,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -257,21 +245,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -292,20 +276,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; @@ -439,7 +420,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor21 { + rb8_slot1: qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -454,9 +435,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -493,11 +471,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -535,7 +508,7 @@ gpio-no-mux = <0>; gpios = <&tlmm 73 0>, <&expander2 2 0>, - <&pmm8654au_0_gpios 8 0>; + <&pmm8654au_0_gpios 8 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -563,11 +536,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -711,7 +679,7 @@ }; /*cam2-ov9282*/ - qcom,cam-sensor22 { + rb8_slot2: qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -726,21 +694,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK2", - "CAMIF_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; clock-names = "cam_clk"; @@ -767,21 +731,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK2", - "CAMIF_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; clock-names = "cam_clk"; @@ -802,21 +762,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; @@ -950,7 +906,7 @@ }; /*cam3-ov9282*/ - qcom,cam-sensor23 { + rb8_slot3: qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; @@ -965,21 +921,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, + gpios = <&tlmm 135 0>, <&pmm8654au_0_gpios 10 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK3", - "CAMIF_RESET3", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; clock-names = "cam_clk"; @@ -1006,21 +958,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, + gpios = <&tlmm 135 0>, <&pmm8654au_0_gpios 10 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK3", - "CAMIF_RESET3", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; clock-names = "cam_clk"; @@ -1041,21 +989,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, - <&pmm8654au_0_gpios 10 0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3", - "CAM_CUSTOM1"; + gpios = <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; From 5f41fed2526c9b3e3f5f0d6b481182ac53adf052 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 2 Jun 2026 11:10:13 +0800 Subject: [PATCH 0625/1058] PENDING: arm64: dts: qcom: kaanapali: add Coresight ETR and routing in staging dtso Add CTCU, QDSS replicator, dual ETR (tmc_etr/tmc_etr1), ETR replicator, SWAO replicator, and tmc_etf out-port to complete the DDR memory trace routing path in the kaanapali staging overlay. Signed-off-by: Jie Gan --- .../boot/dts/qcom/kaanapali-staging.dtso | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso index d7a5b0b084872..39347415c815e 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso +++ b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso @@ -9,6 +9,150 @@ /plugin/; &soc { + ctcu: ctcu@10001000 { + compatible = "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&tmc_etr_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&tmc_etr1_out>; + }; + }; + }; + }; + + replicator_qdss: replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_qdss_in: endpoint { + remote-endpoint = <&replicator_swao_out0>; + }; + }; + }; + + out-ports { + port { + replicator_qdss_out: endpoint { + remote-endpoint = <&replicator_etr_in>; + }; + }; + }; + }; + + tmc_etr: tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x04e0 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr_in: endpoint { + remote-endpoint = <&replicator_etr_out0>; + }; + }; + }; + + out-ports { + port { + tmc_etr_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator_etr: replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_etr_in: endpoint { + remote-endpoint = <&replicator_qdss_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_etr_out0: endpoint { + remote-endpoint = <&tmc_etr_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_etr_out1: endpoint { + remote-endpoint = <&tmc_etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0500 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr1_in: endpoint { + remote-endpoint = <&replicator_etr_out1>; + }; + }; + }; + + out-ports { + port { + tmc_etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tgu@11301000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x11301000 0x0 0x1000>; @@ -17,6 +161,53 @@ clock-names = "apb_pclk"; }; + tmc@11305000 { + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&replicator_swao_in>; + }; + }; + }; + }; + + replicator_swao: replicator@11306000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x11306000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_swao_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_swao_out0: endpoint { + remote-endpoint = <&replicator_qdss_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_swao_out1: endpoint { + remote-endpoint = <&eud_in>; + }; + }; + }; + }; + tgu@1130e000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x1130e000 0x0 0x1000>; From ab164747692542ea3a1034c5f3888ffa4c55bfb9 Mon Sep 17 00:00:00 2001 From: Dipa Ramesh Mantre Date: Tue, 19 May 2026 18:33:38 +0530 Subject: [PATCH 0626/1058] PENDING: arm64: dts: qcom: hamoa: Enable CDSP cooling in staging dtso MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in hamoa. Set up CDSP cooling by throttling the cdsp when it reaches 105°C. Signed-off-by: Dipa Ramesh Mantre --- arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 82 +++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso index feb3c7c5ccd82..6a1e106ae8a9a 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -8,6 +8,8 @@ /dts-v1/; /plugin/; +#include + &soc { tgu@10b0e000 { compatible = "qcom,tgu", "arm,primecell"; @@ -33,3 +35,83 @@ clock-names = "apb_pclk"; }; }; + +&remoteproc_cdsp { + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + + cdsp_tmd0: cdsp-tmd0 { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; +}; + +&thermal_nsp0 { + trips { + nsp0_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp1 { + trips { + nsp1_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp2 { + trips { + nsp2_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp3 { + trips { + nsp3_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + From 8160c08b2c95f65041e2928877555e0d18f3eb44 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 1 Jun 2026 12:39:56 +0530 Subject: [PATCH 0627/1058] QCLINUX: arm64: dts: qcom: Change Purwa camera firmware path Update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi index 5896e5759e22f..fe1057fe97f92 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -34,7 +34,7 @@ src-clock-name = "icp_clk_src"; operating-points-v2 = <&icp_opp_table>; clock-control-debugfs = "true"; - fw_name = "qcom/x1p4x100/CAMERA_ICP"; + fw_name = "qcom/x1p42100/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; ubwc-bps-fetch-cfg = <0x707b 0x7083>; From bb202d53ef00bb969d51ee555964524e913af3d9 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 28 May 2026 17:21:27 +0530 Subject: [PATCH 0628/1058] QCLINUX: arm64: dts: qcom: Add Glymur crd camx overlay dts Add CAMX overlay dts file for Glymur crd boards. This change also enables the compilation of the CAMX overlay for Glymur crd boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 5 + arch/arm64/boot/dts/qcom/glymur-camera.dtsi | 2454 +++++++++++++++++ arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso | 27 + 3 files changed, 2486 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b0353dabaac49..7a2b7de6fb221 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -482,6 +482,11 @@ x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo +glymur-crd-camx-dtbs := glymur-crd.dtb glymur-crd-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtbo + hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi new file mode 100644 index 0000000000000..9e50200f82830 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -0,0 +1,2454 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v2_1"; + icp-version = <0x0201>; + reg = <0x0 0xac01000 0x0 0x1000>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_wd0"; + reg-cam-base = <0x1000 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk", + "camcc_debug_clk"; + clock-rates = <0 300000000 0 0>, + <0 400000000 0 0>, + <0 480000000 0 0>, + <0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/glymur/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&hsc_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <24>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <25>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <26>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <27>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <28>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <29>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <30>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <31>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <32>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <33>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <34>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <35>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <36>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <37>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <38>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <39>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + operating-points-v2 = <&cci1_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x14b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x14400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x14c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x4800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x0000>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* mclk1 */ + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* mclk1 */ + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* mclk2 */ + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* mclk2 */ + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* mclk3 */ + config { + pins = "gpio99"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* mclk3 */ + config { + pins = "gpio99"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cci_i2c_sda0_active: cci_i2c_sda0_active { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci_i2c_sda0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci_i2c_scl0_active { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci_i2c_scl0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci_i2c_sda1_active { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci_i2c_sda1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci_i2c_scl1_active { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci_i2c_scl1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci_i2c_sda2_active { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci_i2c_sda2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci_i2c_scl2_active { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci_i2c_scl2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso new file mode 100644 index 0000000000000..b75789c8aae6b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glymur-camera.dtsi" + +&cam_icp_firmware { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0000>; + }; +}; From 1679498cbd7a6fb299e5473dcd2e135a6ee20fe2 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 5 Jun 2026 16:54:14 +0530 Subject: [PATCH 0629/1058] QCLINUX: arm64: dts: qcom: added ife lite cpas to purwa camera dtsi Added IFE Lite nodes to CPAS to enable proper voting on these paths. Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 114 +++++++++++++-------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi index fe1057fe97f92..cbc9ec0f83aad 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -149,8 +149,8 @@ client-id-based; client-names = "csiphy0", "csiphy4", "cci0", "cci1", "csid0", "csid1", "csid2", "ife0", "ife1", "ife2", "ipe0", - "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", - "cam-cdm-intf0", "bps0", "icp0", "jpeg-dma0", + "rt-cdm0", "rt-cdm1", "rt-cdm2", "cam-cdm-intf0", + "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", "tpg15"; cell-index = <0>; status = "okay"; @@ -230,8 +230,38 @@ parent-node = <&level1_rt0_wr0>; }; - ipe0_all_wr: ipe0-all-wr { + ife1_rdi_stats_pixel_raw_wr: ife1-rdi-stats-pixel-raw-wr { cell-index = <7>; + node-name = "ife1-rdi-stats-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <8>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <9>; node-name = "ipe0-all-wr"; client-name = "ipe0"; traffic-data = ; @@ -243,7 +273,7 @@ }; ipe0_in_rd: ipe0-in-rd { - cell-index = <8>; + cell-index = <10>; node-name = "ipe0-in-rd"; client-name = "ipe0"; traffic-data = ; @@ -252,7 +282,7 @@ }; ipe0_ref_rd: ipe0-ref-rd { - cell-index = <9>; + cell-index = <11>; node-name = "ipe0-ref-rd"; client-name = "ipe0"; traffic-data = ; @@ -261,7 +291,7 @@ }; jpeg_dma0_all_rd: jpeg-dma0-all-rd { - cell-index = <10>; + cell-index = <12>; node-name = "jpeg-dma0-all-rd"; client-name = "jpeg-dma0"; traffic-data = ; @@ -270,7 +300,7 @@ }; jpeg_dma0_all_wr: jpeg-dma0-all-wr { - cell-index = <11>; + cell-index = <13>; node-name = "jpeg-dma0-all-wr"; client-name = "jpeg-dma0"; traffic-data = ; @@ -279,7 +309,7 @@ }; jpeg_enc0_all_rd: jpeg-enc0-all-rd { - cell-index = <12>; + cell-index = <14>; node-name = "jpeg-enc0-all-rd"; client-name = "jpeg-enc0"; traffic-data = ; @@ -288,7 +318,7 @@ }; jpeg_enc0_all_wr: jpeg-enc0-all-wr { - cell-index = <13>; + cell-index = <15>; node-name = "jpeg-enc0-all-wr"; client-name = "jpeg-enc0"; traffic-data = ; @@ -297,7 +327,7 @@ }; rt_cdm0_all_rd: rt-cdm0-all-rd { - cell-index = <14>; + cell-index = <16>; node-name = "rt-cdm0-all-rd"; client-name = "rt-cdm0"; traffic-data = ; @@ -306,20 +336,20 @@ }; /* IFE Lite 0 */ - rt_cdm2_all_rd: rt-cdm2-all-rd { - cell-index = <15>; - node-name = "rt-cdm2-all-rd"; - client-name = "rt-cdm2"; + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <17>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; traffic-data = ; traffic-transaction-type = ; parent-node = <&level1_nrt0_rd1>; }; /* IFE Lite 1 */ - rt_cdm3_all_rd: rt-cdm3-all-rd { - cell-index = <16>; - node-name = "rt-cdm3-all-rd"; - client-name = "rt-cdm3"; + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <18>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; traffic-data = ; traffic-transaction-type = ; parent-node = <&level1_nrt0_rd1>; @@ -331,56 +361,56 @@ camnoc-max-needed; level1_nrt0_rd0: level1-nrt0-rd0 { - cell-index = <17>; + cell-index = <19>; node-name = "level1-nrt0-rd0"; parent-node = <&level2_nrt0_rd>; traffic-merge-type = ; }; level1_nrt0_rd1: level1-nrt0-rd1 { - cell-index = <18>; + cell-index = <20>; node-name = "level1-nrt0-rd1"; parent-node = <&level2_nrt0_rd>; traffic-merge-type = ; }; level1_nrt0_wr0: level1-nrt0-wr0 { - cell-index = <19>; + cell-index = <21>; node-name = "level1-nrt0-wr0"; parent-node = <&level2_nrt0_wr>; traffic-merge-type = ; }; level1_rt0_wr0: level1-rt0-wr0 { - cell-index = <20>; + cell-index = <22>; node-name = "level1-ife-ubwc-wr"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr1: level1-rt0-wr1 { - cell-index = <21>; + cell-index = <23>; node-name = "level1-ife-rdi-wr"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr2: level1-rt0-wr2 { - cell-index = <22>; + cell-index = <24>; node-name = "level1-ife-pdaf"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr3: level1-rt0-wr3 { - cell-index = <23>; + cell-index = <25>; node-name = "level1-ife01-linear-stats"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr4: level1-rt0-wr4 { - cell-index = <24>; + cell-index = <26>; node-name = "level1-ifelite"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; @@ -392,7 +422,7 @@ camnoc-max-needed; level2_nrt0_rd: level2-nrt0-rd { - cell-index = <25>; + cell-index = <27>; node-name = "level2-nrt0-rd"; parent-node = <&level3_nrt0_rd_wr_sum>; traffic-merge-type = @@ -400,7 +430,7 @@ }; level2_nrt0_wr: level2-nrt0-wr { - cell-index = <26>; + cell-index = <28>; node-name = "level2-nrt0-wr"; parent-node = <&level3_nrt0_rd_wr_sum>; traffic-merge-type = @@ -408,7 +438,7 @@ }; level2_nrt1_rd: level2-nrt1-rd { - cell-index = <27>; + cell-index = <29>; node-name = "level2-nrt1-rd"; parent-node = <&level3_nrt1_rd_wr_sum>; traffic-merge-type = ; @@ -416,7 +446,7 @@ }; level2_rt0_rd: level2-rt0-rd { - cell-index = <28>; + cell-index = <30>; node-name = "level2-rt0-rd"; parent-node = <&level3_rt0_rd_wr_sum>; traffic-merge-type = @@ -424,7 +454,7 @@ }; level2_rt0_wr: level2-rt0-wr { - cell-index = <29>; + cell-index = <31>; node-name = "level2-rt0-wr"; parent-node = <&level3_rt0_rd_wr_sum>; traffic-merge-type = @@ -437,7 +467,7 @@ level-index = <3>; level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { - cell-index = <30>; + cell-index = <32>; node-name = "level3-nrt0-rd-wr-sum"; traffic-merge-type = ; qcom,axi-port-mnoc { @@ -446,7 +476,7 @@ }; level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { - cell-index = <31>; + cell-index = <33>; node-name = "level3-nrt1-rd-wr-sum"; traffic-merge-type = ; qcom,axi-port-mnoc { @@ -455,7 +485,7 @@ }; level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { - cell-index = <32>; + cell-index = <34>; node-name = "level3-rt0-rd-wr-sum"; traffic-merge-type = ; ib-bw-voting-needed; @@ -1473,14 +1503,14 @@ }; }; - qcom,rt-cdm2@acf9000 { + qcom,rt-cdm1@acf9000 { compatible = "qcom,cam-rt-cdm2_1"; label = "rt-cdm"; reg = <0x0 0xacf9000 0x0 0x400>; - reg-names = "rt-cdm2"; + reg-names = "rt-cdm1"; reg-cam-base = <0xf9000>; interrupts = ; - interrupt-names = "rt-cdm2"; + interrupt-names = "rt-cdm1"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>; @@ -1497,7 +1527,7 @@ cam_hw_pid = <24>; cam-hw-mid = <0>; single-context-cdm; - cell-index = <2>; + cell-index = <1>; status = "okay"; cdm_cpas_opp_table2: opp-table { @@ -1510,14 +1540,14 @@ }; }; - qcom,rt-cdm3@acfa000 { + qcom,rt-cdm2@acfa000 { compatible = "qcom,cam-rt-cdm2_1"; label = "rt-cdm"; reg = <0x0 0xacfa000 0x0 0x400>; - reg-names = "rt-cdm3"; + reg-names = "rt-cdm2"; reg-cam-base = <0xfa000>; interrupts = ; - interrupt-names = "rt-cdm3"; + interrupt-names = "rt-cdm2"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>; @@ -1534,7 +1564,7 @@ cam_hw_pid = <27>; cam-hw-mid = <0>; single-context-cdm; - cell-index = <3>; + cell-index = <2>; status = "okay"; cdm_cpas_opp_table3: opp-table { From a4d725df2f8015f117c157feb372c633a11156dd Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 5 Jun 2026 17:49:52 +0530 Subject: [PATCH 0630/1058] QCLINUX: arm64: dts: qcom: monaco-evk: disable unused camera regulators vreg_cam0_2p8 and vreg_cam2_2p8 are not used on the Monaco EVK board. Disable them to prevent unintended regulator enablement. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso index c0fea4bb3dc23..0a5265e178feb 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -106,6 +106,14 @@ }; }; +&vreg_cam0_2p8 { + status = "disabled"; +}; + &vreg_cam1_2p8 { status = "disabled"; }; + +&vreg_cam2_2p8 { + status = "disabled"; +}; From fa3bdb686b6f473cffe18b822c3e11572ac79077 Mon Sep 17 00:00:00 2001 From: Sankalp Negi Date: Wed, 10 Jun 2026 10:16:51 -0700 Subject: [PATCH 0631/1058] QCLINUX: dt-bindings: mailbox: qcom-ipcc: Add RTSS client IDs Add IPCC_CLIENT_RTSS0/1/2/3 client ID definitions (27-30) to the qcom-ipcc dt-bindings header for use by the RTSS Mailbox device tree overlay. Signed-off-by: Sankalp Negi --- include/dt-bindings/mailbox/qcom-ipcc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/dt-bindings/mailbox/qcom-ipcc.h b/include/dt-bindings/mailbox/qcom-ipcc.h index fd85a79381b31..b9f358a9b7aee 100644 --- a/include/dt-bindings/mailbox/qcom-ipcc.h +++ b/include/dt-bindings/mailbox/qcom-ipcc.h @@ -33,6 +33,10 @@ #define IPCC_CLIENT_NSP1 18 #define IPCC_CLIENT_TME 23 #define IPCC_CLIENT_WPSS 24 +#define IPCC_CLIENT_RTSS0 27 +#define IPCC_CLIENT_RTSS1 28 +#define IPCC_CLIENT_RTSS2 29 +#define IPCC_CLIENT_RTSS3 30 #define IPCC_CLIENT_GPDSP0 31 #define IPCC_CLIENT_GPDSP1 32 From 1923b1cd3cc1c3211a0108d0ac79f0163aeb0a9b Mon Sep 17 00:00:00 2001 From: Sankalp Negi Date: Wed, 10 Jun 2026 10:16:51 -0700 Subject: [PATCH 0632/1058] QCLINUX: arm64: dts: qcom: lemans: Add RTSS Mailbox device tree overlay Add lemans-rtss-mb.dtso overlay for Lemans platform providing: - ipcc_computeL1: IPCC Compute-L1 controller - rtss_mailbox: RTSS Mailbox device node. Signed-off-by: Sankalp Negi --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso | 65 ++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 7a2b7de6fb221..f023aee3bb31e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -508,6 +508,7 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-rtss-mb.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso b/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso new file mode 100644 index 0000000000000..b1d8996c9ea8b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&soc { + ipcc_computeL1: qcom,ipcc@488000 { + compatible = "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + num_mbox_chans = <5>; + }; + + rtss_mailbox: rtss-mailbox@1ffe02c { + compatible = "qcom,rtss-mailbox"; + reg = <0x0 0x01ffe02c 0x0 0x10>, + <0x0 0x01ffd018 0x0 0x10>, + <0x0 0x17c0000c 0x0 0x04>; + mboxes = <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS3 0x10>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + interrupt-parent = <&ipcc_computeL1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + rtss-handshake-delay = <50000>; + status = "okay"; + }; +}; From 117902228b6747a0d4293ff9b25494e3345c1ae3 Mon Sep 17 00:00:00 2001 From: Sankalp Negi Date: Wed, 10 Jun 2026 10:16:51 -0700 Subject: [PATCH 0633/1058] QCLINUX: arm64: dts: qcom: Monaco: Add RTSS Mailbox device tree overlay Add monaco-rtss-mb.dtso overlay for Monaco platform providing: - ipcc_computeL1: IPCC Compute-L1 controller - rtss_mailbox: RTSS Mailbox device node. Signed-off-by: Sankalp Negi --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso | 65 ++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index f023aee3bb31e..5fbf4f1a8745d 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -522,6 +522,7 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-rtss-mb.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso b/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso new file mode 100644 index 0000000000000..b1d8996c9ea8b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&soc { + ipcc_computeL1: qcom,ipcc@488000 { + compatible = "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + num_mbox_chans = <5>; + }; + + rtss_mailbox: rtss-mailbox@1ffe02c { + compatible = "qcom,rtss-mailbox"; + reg = <0x0 0x01ffe02c 0x0 0x10>, + <0x0 0x01ffd018 0x0 0x10>, + <0x0 0x17c0000c 0x0 0x04>; + mboxes = <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS3 0x10>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + interrupt-parent = <&ipcc_computeL1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + rtss-handshake-delay = <50000>; + status = "okay"; + }; +}; From 57520c4d1a4c1cd708b92401d0d4033657de9329 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 17 Jun 2026 12:11:38 +0530 Subject: [PATCH 0634/1058] QCLINUX: arm64: dts: qcom: Fix ICP IOVA len within 4GB Reduce the ICP iova-region-len to keep the IO region within the valid 4GB addressable range and avoid overflow. This ensures proper IOVA mapping and prevents potential address boundary violations during camera memory configuration. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/glymur-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi index 9e50200f82830..c2c6050a47add 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -1974,7 +1974,7 @@ /* IO region is approximately 3.7 GB */ iova-region-name = "io"; iova-region-start = <0x14c00000>; - iova-region-len = <0xee300000>; + iova-region-len = <0xeb300000>; iova-region-id = <0x3>; status = "okay"; }; From 186de11eb0bd06325248cfc5f7d144dbad54cb38 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 4 Jun 2026 23:53:48 +0530 Subject: [PATCH 0635/1058] QCLINUX: arm64: dts: qcom: Enable camera sensor on glymur crd Enable camera sensors OV08X on the Glymur CRD platform. Adds required DT updates to support sensor bring-up and probe on Glymur crd board. Signed-off-by: Chandan Kumar Jha --- .../boot/dts/qcom/glymur-camera-sensor.dtsi | 51 +++++++++++++++++++ arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso | 13 +++++ 2 files changed, 64 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi new file mode 100644 index 0000000000000..acf015644f483 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci1 { + /*cam0-ov08x*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4p>; + cam_vana-supply = <&vreg_l7p>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 2800000>; + rgltr-max-voltage = <1800000 2800000>; + rgltr-load-current = <204000 55000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 100 0>, + <&tlmm 239 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK4", + "CAMIF_RESET4"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso index b75789c8aae6b..64cea8de94206 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -19,9 +19,22 @@ #include #include "glymur-camera.dtsi" +#include "glymur-camera-sensor.dtsi" &cam_icp_firmware { camera-firmware { iommus = <&apps_smmu 0x1901 0x0000>; }; }; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; + +&cci1_i2c1 { + status = "disabled"; +}; From a1e35a8a87afc9551e735e7f31c4466dc1d1d32c Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 18 Jun 2026 14:41:57 +0800 Subject: [PATCH 0636/1058] QCLINUX: arm64: dts: qcom: Add shared X1 staging overlay Move the common Hamoa staging overlay contents into x1-staging.dtsi so they can be shared across X1 platforms. Keep hamoa-staging.dtso as a thin wrapper around the shared include and add purwa-staging.dtso to build an identical staging overlay for Purwa. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 108 +------------------ arch/arm64/boot/dts/qcom/purwa-staging.dtso | 11 ++ arch/arm64/boot/dts/qcom/x1-staging.dtsi | 113 ++++++++++++++++++++ 4 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/purwa-staging.dtso create mode 100644 arch/arm64/boot/dts/qcom/x1-staging.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 5fbf4f1a8745d..cca3282541992 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -588,6 +588,8 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += purwa-staging.dtbo + dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso index 6a1e106ae8a9a..465e521384842 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -8,110 +8,4 @@ /dts-v1/; /plugin/; -#include - -&soc { - tgu@10b0e000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b0e000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; - - tgu@10b0f000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b0f000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; - - tgu@10b10000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b10000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; -}; - -&remoteproc_cdsp { - cooling { - compatible = "qcom,qmi-cooling-cdsp"; - - cdsp_tmd0: cdsp-tmd0 { - label = "cdsp_sw"; - #cooling-cells = <2>; - }; - }; -}; - -&thermal_nsp0 { - trips { - nsp0_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp0_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp1 { - trips { - nsp1_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp1_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp2 { - trips { - nsp2_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp2_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp3 { - trips { - nsp3_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp3_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/purwa-staging.dtso b/arch/arm64/boot/dts/qcom/purwa-staging.dtso new file mode 100644 index 0000000000000..5ab12052dd80f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-staging.dtso @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Purwa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/x1-staging.dtsi b/arch/arm64/boot/dts/qcom/x1-staging.dtsi new file mode 100644 index 0000000000000..24dfda988bd9d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1-staging.dtsi @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Shared X1 staging device tree modifications. + */ + +#include + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; + +&remoteproc_cdsp { + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + + cdsp_tmd0: cdsp-tmd0 { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; +}; + +&thermal_nsp0 { + trips { + nsp0_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp1 { + trips { + nsp1_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp2 { + trips { + nsp2_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp3 { + trips { + nsp3_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; From 2d7437f06c31181f4f9998e35f75493bec24955e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 22 Jun 2026 15:32:48 +0800 Subject: [PATCH 0637/1058] PENDING: arm64: dts: qcom: kaanapali: add Coresight devices for APSS debug block Add the following devices that are part of the APSS debug block to enable debug features, including ETM, replicator, funnel, and TMC ETF. Signed-off-by: Jie Gan --- .../boot/dts/qcom/kaanapali-staging.dtso | 620 +++++++++++++++++- 1 file changed, 612 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso index 39347415c815e..f6d7ef82d6e39 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso +++ b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso @@ -8,6 +8,120 @@ /dts-v1/; /plugin/; +&{/} { + ete-0 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + ete-1 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + ete-2 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + ete-3 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + ete-4 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + ete-5 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + ete-6 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + ete-7 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; +}; + &soc { ctcu: ctcu@10001000 { compatible = "qcom,sa8775p-ctcu"; @@ -197,14 +311,6 @@ remote-endpoint = <&replicator_qdss_in>; }; }; - - port@1 { - reg = <1>; - - replicator_swao_out1: endpoint { - remote-endpoint = <&eud_in>; - }; - }; }; }; @@ -231,4 +337,502 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; }; + + replicator@1d090000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + funnel@1d021000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + + tn@111b8000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; }; From a90e01cdac0a3bd737b359d3aa9123af75d819da Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Tue, 23 Jun 2026 17:13:53 +0800 Subject: [PATCH 0638/1058] QCLINUX: arm64: dts: qcom: hamoa: Add PM8010_M camera regulator dtsi Add hamoa-camera-regulators.dtsi to define the PM8010_M PMIC LDO regulators needed by camera sensor drivers, and include it in both hamoa-evk-camx.dtso and purwa-evk-camx.dtso. L1M supplies the IMX688 AON core domain (DVDD). It is fed by S5J and supports an output range of 1056-1200 mV. L2M supplies the IMX766 core domain (DVDD). It is fed by S5J and supports an output range of 1152-1200 mV. L3M supplies the IMX766 analog domain and OV sensor I/O (AVDD2, DOVDD). It is fed by S4C and is fixed at 1808 mV. L4M supplies the IMX688 AON I/O domain and IMX766 I/O domain (DOVDD). It is fed by S4C and is fixed at 1808 mV. L5M supplies the IMX766 VCM. It is fed by BOB1 and is fixed at 2960 mV. L6M supplies the IMX688 AON analog domain (AVDD2). It is fed by S4C and is fixed at 1808 mV. L7M supplies the camera analog domain (AVDD). It is fed by BOB1 and is fixed at 2912 mV. Signed-off-by: Tingguo Cheng --- .../dts/qcom/hamoa-camera-regulators.dtsi | 69 +++++++++++++++++++ arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso | 1 + arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 1 + 3 files changed, 71 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi new file mode 100644 index 0000000000000..ac0f603a0ddad --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&apps_rsc { + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l5-supply = <&vreg_bob1>; + vdd-l6-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p1: ldo1 { + regulator-name = "vreg_l1m_1p1"; + regulator-min-microvolt = <1056000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p15: ldo2 { + regulator-name = "vreg_l2m_1p15"; + regulator-min-microvolt = <1152000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l5m_3p0: ldo5 { + regulator-name = "vreg_l5m_3p0"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l6m_1p8: ldo6 { + regulator-name = "vreg_l6m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso index d63daf990f2a1..df773142192eb 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso @@ -18,6 +18,7 @@ #include #include +#include "hamoa-camera-regulators.dtsi" #include "hamoa-camera.dtsi" #include "hamoa-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso index 26603aed4eafc..f97d37cf6e1e4 100644 --- a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -18,6 +18,7 @@ #include #include +#include "hamoa-camera-regulators.dtsi" #include "purwa-camera.dtsi" &camss { From 14c75b09df5108d981a1d6cb9596eb7c14b1a283 Mon Sep 17 00:00:00 2001 From: shubamm Date: Fri, 26 Jun 2026 12:41:17 +0530 Subject: [PATCH 0639/1058] QCLINUX: arm64: dts: qcom: Add Purwa sensors support Add og0va1b IR/VGA camera sensor node. Add imx688 camera sensor module node Signed-off-by: shubamm --- .../boot/dts/qcom/purwa-camera-sensor.dtsi | 89 +++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 1 + 2 files changed, 90 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi diff --git a/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi new file mode 100644 index 0000000000000..ffd6b1c4d570f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso index f97d37cf6e1e4..27d1ff2fc2fea 100644 --- a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -20,6 +20,7 @@ #include "hamoa-camera-regulators.dtsi" #include "purwa-camera.dtsi" +#include "purwa-camera-sensor.dtsi" &camss { status = "disabled"; From c3dbc5f94e0c7e7cc3b9b32912de0af837e3e02b Mon Sep 17 00:00:00 2001 From: shubamm Date: Fri, 26 Jun 2026 12:41:19 +0530 Subject: [PATCH 0640/1058] QCLINUX: arm64: dts: qcom: Add Hamoa camera sensor support Add og0a1b VGA camera sensor node (cam-sensor1) on CCI0 and imx688 camera sensor node (cam-sensor4) on CCI1 for Hamoa board. og0a1b (cam-sensor1): - MCLK0 / CCI master 0 - 1.8V IO supply (vreg_l4m_1p8), 2.9V analog supply (vreg_l7m_2p9) - GPIO reset: TLMM 109, MCLK: TLMM 96 - Sensor position: yaw=180 (rear-facing) imx688 (cam-sensor4): - MCLK4 / CCI1 master 1 - 1.8V IO supply (vreg_l4m_1p8), 1.8V analog supply (vreg_l6m_1p8) - 1.056V digital supply (vreg_l1m_1p1), 2.8V custom supply (vreg_l7b_2p8) - GPIO reset: TLMM 237, MCLK: TLMM 100, custom GPIO: TLMM 233 - Sensor position: yaw=180 (rear-facing) Signed-off-by: shubamm --- .../boot/dts/qcom/hamoa-camera-sensor.dtsi | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi index 7ebfcf1ec3912..a2f821a2b93ff 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -18,8 +18,8 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; + rgltr-min-voltage = <1808000>; + rgltr-max-voltage = <1808000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; pinctrl-names = "cam_default", "cam_suspend"; @@ -43,6 +43,78 @@ cell-index = <0>; status = "okay"; }; + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; }; &soc { From f8b98987a406b6417ec5649acff0b6cf0b554624 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Fri, 5 Jun 2026 01:38:17 +0530 Subject: [PATCH 0641/1058] FROMLIST: drm/msm/a6xx: Fix stale rpmh votes after suspend There are stale RPMH votes (BCM votes) observed after GMU suspend. This is because the rpmh stop sequences are skipped during gmu suspend. Fix this and also move GMU to reset state to avoid any further activity. Link: https://lore.kernel.org/all/20260605-assorted-fixes-june-v1-1-2caa04f7287c@oss.qualcomm.com/ Fixes: f248d5d5159a ("drm/msm/a6xx: Fix PDC sleep sequence") Signed-off-by: Akhil P Oommen Signed-off-by: Shivam Rawat --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 2e5d7b53a0c38..a2f6918c4f7f2 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -642,7 +642,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) int ret; u32 val; - if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) + if (!test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) return; if (adreno_is_a840(adreno_gpu)) @@ -1465,6 +1465,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) /* Stop the interrupts and mask the hardware */ a6xx_gmu_irq_disable(gmu); + /* Halt the gmu cm3 core */ + gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); + /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); From 90139c2b8a897886719fef16fc75a22f7718c830 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Fri, 5 Jun 2026 01:38:18 +0530 Subject: [PATCH 0642/1058] FROMLIST: drm/msm: Recover HW before retire hung submit During recovery, it is not safe to retire the hung submit before we recover the GPU. Retiring the submit triggers BO free and that can result in GPU pagefaults since the GPU may be actively accessing those BOs. To fix this, retire the submits after gpu recovery is complete in recover_worker(). Fixes: 1a370be9ac51 ("drm/msm: restart queued submits after hang") Signed-off-by: Veeresh Bagale Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/linux-arm-msm/20260605-assorted-fixes-june-v1-2-2caa04f7287c@oss.qualcomm.com --- drivers/gpu/drm/msm/msm_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 18ed00e5f143b..9ac7740a87f01 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -552,11 +552,11 @@ static void recover_worker(struct kthread_work *work) msm_update_fence(ring->fctx, fence); } + gpu->funcs->recover(gpu); + /* retire completed submits, plus the one that hung: */ retire_submits(gpu); - gpu->funcs->recover(gpu); - /* * Replay all remaining submits starting with highest priority * ring From 1de9d957f88c5c76930506e2e44d9c8f9af995bb Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Fri, 5 Jun 2026 01:38:19 +0530 Subject: [PATCH 0643/1058] FROMLIST: drm/msm/a6xx: Fix A663 GPUCC register list for state capture The GPUCC register list for A663 is incorrect, which can cause out-of-bounds register access during GPU state capture. Update it to use the correct register ranges. Fixes: 5773cce8615c ("drm/msm/a6xx: Add support for A663") Signed-off-by: Veeresh Bagale Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/linux-arm-msm/20260605-assorted-fixes-june-v1-3-2caa04f7287c@oss.qualcomm.com --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 166365359fa6d..2a62a22077f92 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -1244,7 +1244,9 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], &a6xx_state->gmu_registers[1], true); - if (adreno_is_a621(adreno_gpu) || adreno_is_a623(adreno_gpu)) + if (adreno_is_a621(adreno_gpu) || + adreno_is_a623(adreno_gpu) || + adreno_is_a663(adreno_gpu)) _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, &a6xx_state->gmu_registers[2], false); else From 21e0dc52367e546b2afa3e632f8c93fac5a509af Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Fri, 5 Jun 2026 01:38:20 +0530 Subject: [PATCH 0644/1058] FROMLIST: drm/msm/a6xx: Fix A621 GPUCC register list for state capture A621 uses an incorrect GPUCC register list during state capture. The existing list matches A623/A663. Rename it accordingly and add a dedicated A621 GPUCC register list. Fixes: 11cdb81b3c1b ("drm/msm/a6xx: Fix gpucc register block for A621") Signed-off-by: Veeresh Bagale Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/linux-arm-msm/20260605-assorted-fixes-june-v1-4-2caa04f7287c@oss.qualcomm.com --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 7 ++++--- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 2a62a22077f92..3ea8ff8c74044 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -1244,11 +1244,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], &a6xx_state->gmu_registers[1], true); - if (adreno_is_a621(adreno_gpu) || - adreno_is_a623(adreno_gpu) || - adreno_is_a663(adreno_gpu)) + if (adreno_is_a621(adreno_gpu)) _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, &a6xx_state->gmu_registers[2], false); + else if (adreno_is_a623(adreno_gpu) || adreno_is_a663(adreno_gpu)) + _a6xx_get_gmu_registers(gpu, a6xx_state, &a623_gpucc_reg, + &a6xx_state->gmu_registers[2], false); else _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, &a6xx_state->gmu_registers[2], false); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index b49d8427b59e6..0a13a65f89ac8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -377,6 +377,17 @@ static const u32 a6xx_gmu_gpucc_registers[] = { }; static const u32 a621_gmu_gpucc_registers[] = { + /* GPU CC */ + 0x24000, 0x2400e, 0x24400, 0x2440e, 0x24800, 0x24805, 0x24c00, 0x24cff, + 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, 0x26400, 0x26405, + 0x26414, 0x2641d, 0x2642a, 0x26430, 0x26432, 0x26432, 0x26441, 0x26455, + 0x26466, 0x26468, 0x26478, 0x2647a, 0x26489, 0x2648a, 0x2649c, 0x2649e, + 0x264a0, 0x264a3, 0x264b3, 0x264b5, 0x264c5, 0x264c7, 0x264d6, 0x264d8, + 0x264e8, 0x264e9, 0x264f9, 0x264fc, 0x2650b, 0x2650c, 0x2651c, 0x2651e, + 0x26540, 0x26570, 0x26600, 0x26616, 0x26620, 0x2662d, +}; + +static const u32 a623_gmu_gpucc_registers[] = { /* GPU CC */ 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x26430, @@ -402,6 +413,7 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); +static const struct a6xx_registers a623_gpucc_reg = REGS(a623_gmu_gpucc_registers, 0, 0); static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); From 4234afccbea541e156a01dcb73a546665be0fd1b Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Fri, 5 Jun 2026 01:38:21 +0530 Subject: [PATCH 0645/1058] FROMLIST: drm/msm/a6xx: Fix IRQ storm during msm_recovery test Once a hang is triggered by the msm_recovery test, the gpu error irq remains asserted and triggers an interrupt storm. In the worst case, this IRQ storm lands on the CPU core where the hangcheck timer is scheduled, blocking it from running. This eventually leads to CPU watchdog timeouts. To fix this, mask the gpu error irqs during msm_recovery test and enable them back during the recovery. Fixes: 5edf2750d998 ("drm/msm: Add debugfs to disable hw err handling") Signed-off-by: Veeresh Bagale Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/linux-arm-msm/20260605-assorted-fixes-june-v1-5-2caa04f7287c@oss.qualcomm.com --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 5 +++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 5 ++++- drivers/gpu/drm/msm/adreno/a8xx_gpu.c | 5 ++++- drivers/gpu/drm/msm/msm_gpu.c | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 2c0bbac43c52b..f1df2514c6132 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1275,6 +1275,11 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR); if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, + A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | + A5XX_RBBM_INT_0_MASK_CP_SW); + status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | A5XX_RBBM_INT_0_MASK_CP_SW; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 8b3bb2fd433ba..9a4f9d0e17800 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1911,8 +1911,11 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); - if (priv->disable_err_irq) + if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; + } if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) a6xx_fault_detect_irq(gpu); diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c index 9e44fd1ae6346..0f6fd35bd5878 100644 --- a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c @@ -1211,8 +1211,11 @@ irqreturn_t a8xx_irq(struct msm_gpu *gpu) gpu_write(gpu, REG_A8XX_RBBM_INT_CLEAR_CMD, status); - if (priv->disable_err_irq) + if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A8XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; + } if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) a8xx_fault_detect_irq(gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 9ac7740a87f01..48ac51f4119be 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -552,6 +552,8 @@ static void recover_worker(struct kthread_work *work) msm_update_fence(ring->fctx, fence); } + priv->disable_err_irq = false; + gpu->funcs->recover(gpu); /* retire completed submits, plus the one that hung: */ From 4433b066ef8096363c84ab1e9fc6f71e465ac95f Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Fri, 5 Jun 2026 01:38:22 +0530 Subject: [PATCH 0646/1058] FROMLIST: drm/msm: Fix task_struct reference leak in recover_worker get_pid_task() increments the task reference count, but the corresponding put_task_struct() was missing in the else branch, leaking a reference on every GPU hang recovery. Fixes: 25654a1756a4 ("drm/msm: Update global fault counter when faulty process has already ended") Signed-off-by: Veeresh Bagale Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/linux-arm-msm/20260605-assorted-fixes-june-v1-6-2caa04f7287c@oss.qualcomm.com --- drivers/gpu/drm/msm/msm_gpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 48ac51f4119be..03c0578560658 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -505,6 +505,8 @@ static void recover_worker(struct kthread_work *work) */ if (!vm->managed) msm_gem_vm_unusable(submit->vm); + + put_task_struct(task); } noreclaim_flag = memalloc_noreclaim_save(); From 79149ef6a826d6237346aa74eca65ccbe19d761f Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:39 +0530 Subject: [PATCH 0647/1058] FROMLIST: Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now" This reverts commit 602cb14e310a ("pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"). PDC interrupts no more break GPIOs. PDC is now set to pass through mode which allows GPIO interrupts to setup as wakeup capable at PDC and pass them to GIC as SPIs. Update nwakeirq_map to reflect the GPIO to PDC irq map size. Link: https://lore.kernel.org/all/20260616-hamoa_pdc_v3-v3-7-4d8e1504ea75@oss.qualcomm.com/ Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- drivers/pinctrl/qcom/pinctrl-x1e80100.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c index 8d2b8246170b4..e4c0abcd95b9f 100644 --- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -1836,9 +1836,7 @@ static const struct msm_pinctrl_soc_data x1e80100_pinctrl = { .ngroups = ARRAY_SIZE(x1e80100_groups), .ngpios = 239, .wakeirq_map = x1e80100_pdc_map, - /* TODO: Enabling PDC currently breaks GPIO interrupts */ - .nwakeirq_map = 0, - /* .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), */ + .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), .egpio_func = 9, }; From 5ea8307eb1d0a31d5db7861b8c49cba774672d7d Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:52 +0530 Subject: [PATCH 0648/1058] FROMLIST: dt-bindings: clock: qcom: Add video clock controller on Qualcomm Eliza SoC Eliza Video clock controller is on CX and MX rails similar to Milos. Add compatible string for Eliza video clock controller to the existing Milos videocc binding and add the dt-bindings header for Eliza. The video clock controller exposes power domains, so '#power-domain-cells' must be present in the device node. Add it to the required properties list to enforce this in binding validation. There is no ABI breakage and no impact to the existing devices, since the nodes using this binding already specify the '#power-domain-cells' property for videocc. Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-1-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,milos-videocc.yaml | 10 ++++- .../dt-bindings/clock/qcom,eliza-videocc.h | 37 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/clock/qcom,eliza-videocc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml index 14c31efe1308a..c0c9e450b8cda 100644 --- a/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml @@ -8,16 +8,21 @@ title: Qualcomm Video Clock & Reset Controller on Milos maintainers: - Luca Weiss + - Taniya Das description: | Qualcomm video clock control module provides the clocks, resets and power domains on Milos. - See also: include/dt-bindings/clock/qcom,milos-videocc.h + See also: + include/dt-bindings/clock/qcom,eliza-videocc.h + include/dt-bindings/clock/qcom,milos-videocc.h properties: compatible: - const: qcom,milos-videocc + enum: + - qcom,eliza-videocc + - qcom,milos-videocc clocks: items: @@ -29,6 +34,7 @@ properties: required: - compatible - clocks + - '#power-domain-cells' allOf: - $ref: qcom,gcc.yaml# diff --git a/include/dt-bindings/clock/qcom,eliza-videocc.h b/include/dt-bindings/clock/qcom,eliza-videocc.h new file mode 100644 index 0000000000000..1e922250a7fae --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-videocc.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H + +/* VIDEO_CC clocks */ +#define VIDEO_CC_AHB_CLK 0 +#define VIDEO_CC_AHB_CLK_SRC 1 +#define VIDEO_CC_MVS0_CLK 2 +#define VIDEO_CC_MVS0_CLK_SRC 3 +#define VIDEO_CC_MVS0_DIV_CLK_SRC 4 +#define VIDEO_CC_MVS0_SHIFT_CLK 5 +#define VIDEO_CC_MVS0C_CLK 6 +#define VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC 7 +#define VIDEO_CC_MVS0C_SHIFT_CLK 8 +#define VIDEO_CC_PLL0 9 +#define VIDEO_CC_SLEEP_CLK 10 +#define VIDEO_CC_SLEEP_CLK_SRC 11 +#define VIDEO_CC_XO_CLK 12 +#define VIDEO_CC_XO_CLK_SRC 13 + +/* VIDEO_CC power domains */ +#define VIDEO_CC_MVS0_GDSC 0 +#define VIDEO_CC_MVS0C_GDSC 1 + +/* VIDEO_CC resets */ +#define VIDEO_CC_INTERFACE_BCR 0 +#define VIDEO_CC_MVS0_CLK_ARES 1 +#define VIDEO_CC_MVS0_BCR 2 +#define VIDEO_CC_MVS0C_CLK_ARES 3 +#define VIDEO_CC_MVS0C_BCR 4 +#define VIDEO_CC_XO_CLK_ARES 5 + +#endif From 900f1bef23db013378874ef93d0cfc6736a3a91b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:53 +0530 Subject: [PATCH 0649/1058] FROMLIST: dt-bindings: clock: qcom: document the Eliza GPU Clock Controller Add bindings documentation for the Eliza Graphics Clock Controller. Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-2-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,sm8450-gpucc.yaml | 3 ++ include/dt-bindings/clock/qcom,eliza-gpucc.h | 51 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,eliza-gpucc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml index fdbdf605ee695..734bab762a308 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml @@ -15,6 +15,7 @@ description: | domains on Qualcomm SoCs. See also: + include/dt-bindings/clock/qcom,eliza-gpucc.h include/dt-bindings/clock/qcom,glymur-gpucc.h include/dt-bindings/clock/qcom,kaanapali-gpucc.h include/dt-bindings/clock/qcom,milos-gpucc.h @@ -30,6 +31,7 @@ description: | properties: compatible: enum: + - qcom,eliza-gpucc - qcom,glymur-gpucc - qcom,kaanapali-gpucc - qcom,milos-gpucc @@ -71,6 +73,7 @@ allOf: compatible: contains: enum: + - qcom,eliza-gpucc - qcom,sm8750-gpucc then: required: diff --git a/include/dt-bindings/clock/qcom,eliza-gpucc.h b/include/dt-bindings/clock/qcom,eliza-gpucc.h new file mode 100644 index 0000000000000..c3d9b7827325c --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-gpucc.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H + +/* GPU_CC clocks */ +#define GPU_CC_AHB_CLK 0 +#define GPU_CC_CRC_AHB_CLK 1 +#define GPU_CC_CX_ACCU_SHIFT_CLK 2 +#define GPU_CC_CX_FF_CLK 3 +#define GPU_CC_CX_GMU_CLK 4 +#define GPU_CC_CXO_AON_CLK 5 +#define GPU_CC_CXO_CLK 6 +#define GPU_CC_DEMET_CLK 7 +#define GPU_CC_DEMET_DIV_CLK_SRC 8 +#define GPU_CC_FF_CLK_SRC 9 +#define GPU_CC_FREQ_MEASURE_CLK 10 +#define GPU_CC_GMU_CLK_SRC 11 +#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 12 +#define GPU_CC_HUB_AON_CLK 13 +#define GPU_CC_HUB_CLK_SRC 14 +#define GPU_CC_HUB_CX_INT_CLK 15 +#define GPU_CC_MEMNOC_GFX_CLK 16 +#define GPU_CC_MND1X_0_GFX3D_CLK 17 +#define GPU_CC_MND1X_1_GFX3D_CLK 18 +#define GPU_CC_PLL0 19 +#define GPU_CC_PLL1 20 +#define GPU_CC_SLEEP_CLK 21 +#define GPU_CC_XO_CLK_SRC 22 +#define GPU_CC_XO_DIV_CLK_SRC 23 + +/* GPU_CC power domains */ +#define GPU_CC_CX_GDSC 0 +#define GPU_CC_GX_GDSC 1 + +/* GPU_CC resets */ +#define GPU_CC_ACD_BCR 0 +#define GPU_CC_CB_BCR 1 +#define GPU_CC_CX_BCR 2 +#define GPU_CC_FAST_HUB_BCR 3 +#define GPU_CC_FF_BCR 4 +#define GPU_CC_GFX3D_AON_BCR 5 +#define GPU_CC_GMU_BCR 6 +#define GPU_CC_GX_BCR 7 +#define GPU_CC_RBCPR_BCR 8 +#define GPU_CC_XO_BCR 9 + +#endif From 66736910c318a3d0ee252d018fe4b5ec1783b2c0 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:54 +0530 Subject: [PATCH 0650/1058] FROMLIST: dt-bindings: clock: qcom: Add support for CAMCC for Eliza Eliza camera clock controller is on CX and MX rails similar to Milos. Add compatible string for Eliza camera and camera BIST clock controller to the existing Milos camcc binding and add the dt-bindings header for Eliza. The camera clock controller provides power domains, so 'power-domain-cells' must be present in the device tree node. Add this to required properties to enforce it in the binding schema. Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-3-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,milos-camcc.yaml | 12 +- .../clock/qcom,eliza-cambistmclkcc.h | 32 ++++ include/dt-bindings/clock/qcom,eliza-camcc.h | 151 ++++++++++++++++++ 3 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h create mode 100644 include/dt-bindings/clock/qcom,eliza-camcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml index 707b25d2c11e6..efafe86e1238d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml @@ -8,16 +8,23 @@ title: Qualcomm Camera Clock & Reset Controller on Milos maintainers: - Luca Weiss + - Taniya Das description: | Qualcomm camera clock control module provides the clocks, resets and power domains on Milos. - See also: include/dt-bindings/clock/qcom,milos-camcc.h + See also: + include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h + include/dt-bindings/clock/qcom,eliza-camcc.h + include/dt-bindings/clock/qcom,milos-camcc.h properties: compatible: - const: qcom,milos-camcc + enum: + - qcom,eliza-cambistmclkcc + - qcom,eliza-camcc + - qcom,milos-camcc clocks: items: @@ -32,6 +39,7 @@ properties: required: - compatible - clocks + - '#power-domain-cells' allOf: - $ref: qcom,gcc.yaml# diff --git a/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h new file mode 100644 index 0000000000000..7b8b285f18d27 --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H + +/* CAM_BIST_MCLK_CC clocks */ +#define CAM_BIST_MCLK_CC_MCLK0_CLK 0 +#define CAM_BIST_MCLK_CC_MCLK0_CLK_SRC 1 +#define CAM_BIST_MCLK_CC_MCLK1_CLK 2 +#define CAM_BIST_MCLK_CC_MCLK1_CLK_SRC 3 +#define CAM_BIST_MCLK_CC_MCLK2_CLK 4 +#define CAM_BIST_MCLK_CC_MCLK2_CLK_SRC 5 +#define CAM_BIST_MCLK_CC_MCLK3_CLK 6 +#define CAM_BIST_MCLK_CC_MCLK3_CLK_SRC 7 +#define CAM_BIST_MCLK_CC_MCLK4_CLK 8 +#define CAM_BIST_MCLK_CC_MCLK4_CLK_SRC 9 +#define CAM_BIST_MCLK_CC_MCLK5_CLK 10 +#define CAM_BIST_MCLK_CC_MCLK5_CLK_SRC 11 +#define CAM_BIST_MCLK_CC_MCLK6_CLK 12 +#define CAM_BIST_MCLK_CC_MCLK6_CLK_SRC 13 +#define CAM_BIST_MCLK_CC_MCLK7_CLK 14 +#define CAM_BIST_MCLK_CC_MCLK7_CLK_SRC 15 +#define CAM_BIST_MCLK_CC_PLL0 16 +#define CAM_BIST_MCLK_CC_PLL_TEST_CLK 17 +#define CAM_BIST_MCLK_CC_PLL_TEST_DIV_CLK_SRC 18 +#define CAM_BIST_MCLK_CC_SLEEP_CLK 19 +#define CAM_BIST_MCLK_CC_SLEEP_CLK_SRC 20 + +#endif diff --git a/include/dt-bindings/clock/qcom,eliza-camcc.h b/include/dt-bindings/clock/qcom,eliza-camcc.h new file mode 100644 index 0000000000000..d85ef9777d08d --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-camcc.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H + +/* CAM_CC clocks */ +#define CAM_CC_CAM_TOP_AHB_CLK 0 +#define CAM_CC_CAM_TOP_FAST_AHB_CLK 1 +#define CAM_CC_CAMNOC_DCD_XO_CLK 2 +#define CAM_CC_CAMNOC_NRT_AXI_CLK 3 +#define CAM_CC_CAMNOC_NRT_CRE_CLK 4 +#define CAM_CC_CAMNOC_NRT_IPE_NPS_CLK 5 +#define CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK 6 +#define CAM_CC_CAMNOC_NRT_OFE_HDR_CLK 7 +#define CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK 8 +#define CAM_CC_CAMNOC_RT_AXI_CLK 9 +#define CAM_CC_CAMNOC_RT_AXI_CLK_SRC 10 +#define CAM_CC_CAMNOC_RT_IFE_LITE_CLK 11 +#define CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK 12 +#define CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK 13 +#define CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK 14 +#define CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK 15 +#define CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK 16 +#define CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK 17 +#define CAM_CC_CAMNOC_XO_CLK 18 +#define CAM_CC_CCI_0_CLK 19 +#define CAM_CC_CCI_0_CLK_SRC 20 +#define CAM_CC_CCI_1_CLK 21 +#define CAM_CC_CCI_1_CLK_SRC 22 +#define CAM_CC_CCI_2_CLK 23 +#define CAM_CC_CCI_2_CLK_SRC 24 +#define CAM_CC_CORE_AHB_CLK 25 +#define CAM_CC_CPHY_RX_CLK_SRC 26 +#define CAM_CC_CRE_AHB_CLK 27 +#define CAM_CC_CRE_CLK 28 +#define CAM_CC_CRE_CLK_SRC 29 +#define CAM_CC_CSI0PHYTIMER_CLK 30 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 31 +#define CAM_CC_CSI1PHYTIMER_CLK 32 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 33 +#define CAM_CC_CSI2PHYTIMER_CLK 34 +#define CAM_CC_CSI2PHYTIMER_CLK_SRC 35 +#define CAM_CC_CSI3PHYTIMER_CLK 36 +#define CAM_CC_CSI3PHYTIMER_CLK_SRC 37 +#define CAM_CC_CSI4PHYTIMER_CLK 38 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 39 +#define CAM_CC_CSI5PHYTIMER_CLK 40 +#define CAM_CC_CSI5PHYTIMER_CLK_SRC 41 +#define CAM_CC_CSID_CLK 42 +#define CAM_CC_CSID_CLK_SRC 43 +#define CAM_CC_CSID_CSIPHY_RX_CLK 44 +#define CAM_CC_CSIPHY0_CLK 45 +#define CAM_CC_CSIPHY1_CLK 46 +#define CAM_CC_CSIPHY2_CLK 47 +#define CAM_CC_CSIPHY3_CLK 48 +#define CAM_CC_CSIPHY4_CLK 49 +#define CAM_CC_CSIPHY5_CLK 50 +#define CAM_CC_DRV_AHB_CLK 51 +#define CAM_CC_DRV_XO_CLK 52 +#define CAM_CC_FAST_AHB_CLK_SRC 53 +#define CAM_CC_GDSC_CLK 54 +#define CAM_CC_ICP_0_AHB_CLK 55 +#define CAM_CC_ICP_0_CLK 56 +#define CAM_CC_ICP_0_CLK_SRC 57 +#define CAM_CC_ICP_1_AHB_CLK 58 +#define CAM_CC_ICP_1_CLK 59 +#define CAM_CC_ICP_1_CLK_SRC 60 +#define CAM_CC_IFE_LITE_AHB_CLK 61 +#define CAM_CC_IFE_LITE_CLK 62 +#define CAM_CC_IFE_LITE_CLK_SRC 63 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 64 +#define CAM_CC_IFE_LITE_CSID_CLK 65 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 66 +#define CAM_CC_IPE_NPS_AHB_CLK 67 +#define CAM_CC_IPE_NPS_CLK 68 +#define CAM_CC_IPE_NPS_CLK_SRC 69 +#define CAM_CC_IPE_NPS_FAST_AHB_CLK 70 +#define CAM_CC_IPE_PPS_CLK 71 +#define CAM_CC_IPE_PPS_FAST_AHB_CLK 72 +#define CAM_CC_JPEG_0_CLK 73 +#define CAM_CC_JPEG_1_CLK 74 +#define CAM_CC_JPEG_CLK_SRC 75 +#define CAM_CC_OFE_AHB_CLK 76 +#define CAM_CC_OFE_ANCHOR_CLK 77 +#define CAM_CC_OFE_ANCHOR_FAST_AHB_CLK 78 +#define CAM_CC_OFE_CLK_SRC 79 +#define CAM_CC_OFE_HDR_CLK 80 +#define CAM_CC_OFE_HDR_FAST_AHB_CLK 81 +#define CAM_CC_OFE_MAIN_CLK 82 +#define CAM_CC_OFE_MAIN_FAST_AHB_CLK 83 +#define CAM_CC_PLL0 84 +#define CAM_CC_PLL0_OUT_EVEN 85 +#define CAM_CC_PLL0_OUT_ODD 86 +#define CAM_CC_PLL1 87 +#define CAM_CC_PLL1_OUT_EVEN 88 +#define CAM_CC_PLL2 89 +#define CAM_CC_PLL2_OUT_EVEN 90 +#define CAM_CC_PLL3 91 +#define CAM_CC_PLL3_OUT_EVEN 92 +#define CAM_CC_PLL4 93 +#define CAM_CC_PLL4_OUT_EVEN 94 +#define CAM_CC_PLL5 95 +#define CAM_CC_PLL5_OUT_EVEN 96 +#define CAM_CC_PLL6 97 +#define CAM_CC_PLL6_OUT_EVEN 98 +#define CAM_CC_PLL6_OUT_ODD 99 +#define CAM_CC_QDSS_DEBUG_CLK 100 +#define CAM_CC_QDSS_DEBUG_CLK_SRC 101 +#define CAM_CC_QDSS_DEBUG_XO_CLK 102 +#define CAM_CC_SLEEP_CLK 103 +#define CAM_CC_SLEEP_CLK_SRC 104 +#define CAM_CC_SLOW_AHB_CLK_SRC 105 +#define CAM_CC_TFE_0_BAYER_CLK 106 +#define CAM_CC_TFE_0_BAYER_FAST_AHB_CLK 107 +#define CAM_CC_TFE_0_CLK_SRC 108 +#define CAM_CC_TFE_0_MAIN_CLK 109 +#define CAM_CC_TFE_0_MAIN_FAST_AHB_CLK 110 +#define CAM_CC_TFE_1_BAYER_CLK 111 +#define CAM_CC_TFE_1_BAYER_FAST_AHB_CLK 112 +#define CAM_CC_TFE_1_CLK_SRC 113 +#define CAM_CC_TFE_1_MAIN_CLK 114 +#define CAM_CC_TFE_1_MAIN_FAST_AHB_CLK 115 +#define CAM_CC_TFE_2_BAYER_CLK 116 +#define CAM_CC_TFE_2_BAYER_FAST_AHB_CLK 117 +#define CAM_CC_TFE_2_CLK_SRC 118 +#define CAM_CC_TFE_2_MAIN_CLK 119 +#define CAM_CC_TFE_2_MAIN_FAST_AHB_CLK 120 +#define CAM_CC_XO_CLK_SRC 121 + +/* CAM_CC power domains */ +#define CAM_CC_IPE_0_GDSC 0 +#define CAM_CC_OFE_GDSC 1 +#define CAM_CC_TFE_0_GDSC 2 +#define CAM_CC_TFE_1_GDSC 3 +#define CAM_CC_TFE_2_GDSC 4 +#define CAM_CC_TITAN_TOP_GDSC 5 + +/* CAM_CC resets */ +#define CAM_CC_DRV_BCR 0 +#define CAM_CC_ICP_BCR 1 +#define CAM_CC_IPE_0_BCR 2 +#define CAM_CC_OFE_BCR 3 +#define CAM_CC_QDSS_DEBUG_BCR 4 +#define CAM_CC_TFE_0_BCR 5 +#define CAM_CC_TFE_1_BCR 6 +#define CAM_CC_TFE_2_BCR 7 + +#endif From 82f383b029f0008dafd19412ba3f3f15ccf0130e Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:55 +0530 Subject: [PATCH 0651/1058] FROMLIST: clk: qcom: videocc: Add video clock controller driver for Eliza Add support for the video clock controller for video clients to be able to request for videocc clocks on Eliza platform. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-4-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 10 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/videocc-eliza.c | 404 +++++++++++++++++++++++++++++++ 3 files changed, 415 insertions(+) create mode 100644 drivers/clk/qcom/videocc-eliza.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 3a275bbd5c578..d98bdd919cd35 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -45,6 +45,16 @@ config CLK_ELIZA_TCSRCC Support for the TCSR clock controller on Eliza devices. Say Y if you want to use peripheral devices such as USB/PCIe/UFS. +config CLK_ELIZA_VIDEOCC + tristate "Eliza Video Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the video clock controller on Eliza devices. + Say Y if you want to support video devices and functionality such as + video encode and decode. + config CLK_GLYMUR_CAMCC tristate "Glymur Camera Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 63623651a9e1f..523b4c9b3fb54 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o +obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o obj-$(CONFIG_CLK_GLYMUR_CAMCC) += camcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o diff --git a/drivers/clk/qcom/videocc-eliza.c b/drivers/clk/qcom/videocc-eliza.c new file mode 100644 index 0000000000000..36af35e070299 --- /dev/null +++ b/drivers/clk/qcom/videocc-eliza.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_SLEEP_CLK, + P_VIDEO_CC_PLL0_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 576.0 MHz Configuration */ +static const struct alpha_pll_config video_cc_pll0_config = { + .l = 0x1e, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll video_cc_pll0 = { + .offset = 0x0, + .config = &video_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_2[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_ahb_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_ahb_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(633000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1113000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_sleep_clk_src = { + .cmd_rcgr = 0x8110, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_sleep_clk_src", + .parent_data = video_cc_parent_data_2, + .num_parents = ARRAY_SIZE(video_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 video_cc_xo_clk_src = { + .cmd_rcgr = 0x80f4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_xo_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0x80ac, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8058, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0x80a0, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80a0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0_shift_clk = { + .halt_reg = 0x8144, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8144, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0x804c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_shift_clk = { + .halt_reg = 0x8148, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8148, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc video_cc_mvs0c_gdsc = { + .gdscr = 0x8034, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs0_gdsc = { + .gdscr = 0x808c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs0c_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL_TRIGGER, +}; + +static struct clk_regmap *video_cc_eliza_clocks[] = { + [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr, + [VIDEO_CC_PLL0] = &video_cc_pll0.clkr, + [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, + [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, +}; + +static struct gdsc *video_cc_eliza_gdscs[] = { + [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, + [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, +}; + +static const struct qcom_reset_map video_cc_eliza_resets[] = { + [VIDEO_CC_INTERFACE_BCR] = { 0x80d8 }, + [VIDEO_CC_MVS0_CLK_ARES] = { 0x80a0, 2 }, + [VIDEO_CC_MVS0_BCR] = { 0x8088 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, + [VIDEO_CC_MVS0C_BCR] = { 0x8030 }, + [VIDEO_CC_XO_CLK_ARES] = { 0x810c, 2 }, +}; + +static struct clk_alpha_pll *video_cc_eliza_plls[] = { + &video_cc_pll0, +}; + +static u32 video_cc_eliza_critical_cbcrs[] = { + 0x80dc, /* VIDEO_CC_AHB_CLK */ + 0x8128, /* VIDEO_CC_SLEEP_CLK */ + 0x810c, /* VIDEO_CC_XO_CLK */ +}; + +static const struct regmap_config video_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f50, + .fast_io = true, +}; + +static struct qcom_cc_driver_data video_cc_eliza_driver_data = { + .alpha_plls = video_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(video_cc_eliza_plls), + .clk_cbcrs = video_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(video_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc video_cc_eliza_desc = { + .config = &video_cc_eliza_regmap_config, + .clks = video_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(video_cc_eliza_clocks), + .resets = video_cc_eliza_resets, + .num_resets = ARRAY_SIZE(video_cc_eliza_resets), + .gdscs = video_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_eliza_gdscs), + .driver_data = &video_cc_eliza_driver_data, +}; + +static const struct of_device_id video_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_eliza_match_table); + +static int video_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &video_cc_eliza_desc); +} + +static struct platform_driver video_cc_eliza_driver = { + .probe = video_cc_eliza_probe, + .driver = { + .name = "videocc-eliza", + .of_match_table = video_cc_eliza_match_table, + }, +}; + +module_platform_driver(video_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI VIDEOCC Eliza Driver"); +MODULE_LICENSE("GPL"); From f7294956414840102358ebdc2fed6e0c786bad5f Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:56 +0530 Subject: [PATCH 0652/1058] FROMLIST: clk: qcom: gpucc: Add GPU Clock Controller driver for Eliza Add Graphics Clock Controller (GPUCC) support for Eliza platform. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-5-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 10 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-eliza.c | 607 +++++++++++++++++++++++++++++++++ 3 files changed, 618 insertions(+) create mode 100644 drivers/clk/qcom/gpucc-eliza.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index d98bdd919cd35..80f4a7e0ccde3 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -37,6 +37,16 @@ config CLK_ELIZA_GCC Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, UFS, SDCC, etc. +config CLK_ELIZA_GPUCC + tristate "Eliza Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the graphics clock controller on Eliza devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config CLK_ELIZA_TCSRCC tristate "Eliza TCSR Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 523b4c9b3fb54..0bbc792492178 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o +obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o diff --git a/drivers/clk/qcom/gpucc-eliza.c b/drivers/clk/qcom/gpucc-eliza.c new file mode 100644 index 0000000000000..18525d1c7d033 --- /dev/null +++ b/drivers/clk/qcom/gpucc-eliza.c @@ -0,0 +1,607 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_GPLL0_OUT_MAIN, + DT_GPLL0_OUT_MAIN_DIV, +}; + +enum { + P_BI_TCXO, + P_BI_TCXO_AO, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 518.0 MHz Configuration */ +static const struct alpha_pll_config gpu_cc_pll0_config = { + .l = 0x1a, + .alpha = 0xfaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll0 = { + .offset = 0x0, + .config = &gpu_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +/* 440.0 MHz Configuration */ +static const struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x16, + .alpha = 0xeaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x1000, + .config = &gpu_cc_pll1_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_ff_clk_src = { + .cmd_rcgr = 0x94b8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ff_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x935c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_1, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gpu_cc_hub_clk_src = { + .cmd_rcgr = 0x9430, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_2, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_clk_src", + .parent_data = gpu_cc_parent_data_2, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_xo_clk_src = { + .cmd_rcgr = 0x9010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_3, + .freq_tbl = ftbl_gpu_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_clk_src", + .parent_data = gpu_cc_parent_data_3, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_xo_div_clk_src = { + .reg = 0x9050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x914c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x914c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x9150, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9150, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_crc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_accu_shift_clk = { + .halt_reg = 0x9480, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9480, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_accu_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_ff_clk = { + .halt_reg = 0x9184, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9184, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_ff_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_ff_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x916c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x916c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x917c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x917c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cxo_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_freq_measure_clk = { + .halt_reg = 0x9008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_freq_measure_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { + .halt_reg = 0x7000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_aon_clk = { + .halt_reg = 0x942c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x942c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_aon_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_cx_int_clk = { + .halt_reg = 0x9180, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9180, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_cx_int_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_memnoc_gfx_clk = { + .halt_reg = 0x9188, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9188, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = { + .halt_reg = 0x92cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x92cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_0_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = { + .halt_reg = 0x92d0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x92d0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_1_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x9164, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9164, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cc_cx_gdsc = { + .gdscr = 0x9110, + .gds_hw_ctrl = 0x9124, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x8, + .pd = { + .name = "gpu_cc_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE | RETAIN_FF_ENABLE, +}; + +static struct gdsc gpu_cc_gx_gdsc = { + .gdscr = 0x905c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gpu_cc_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gpu_cc_eliza_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr, + [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, + [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, + [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, + [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, + [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, + [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, + [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr, + [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr, + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, + [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr, + [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr, +}; + +static struct gdsc *gpu_cc_eliza_gdscs[] = { + [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, + [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc, +}; + +static const struct qcom_reset_map gpu_cc_eliza_resets[] = { + [GPU_CC_ACD_BCR] = { 0x939c }, + [GPU_CC_CB_BCR] = { 0x93e4 }, + [GPU_CC_CX_BCR] = { 0x910c }, + [GPU_CC_FAST_HUB_BCR] = { 0x9428 }, + [GPU_CC_FF_BCR] = { 0x94b4 }, + [GPU_CC_GFX3D_AON_BCR] = { 0x91dc }, + [GPU_CC_GMU_BCR] = { 0x9358 }, + [GPU_CC_GX_BCR] = { 0x9058 }, + [GPU_CC_RBCPR_BCR] = { 0x9224 }, + [GPU_CC_XO_BCR] = { 0x9000 }, +}; + +static struct clk_alpha_pll *gpu_cc_eliza_plls[] = { + &gpu_cc_pll0, + &gpu_cc_pll1, +}; + +static u32 gpu_cc_eliza_critical_cbcrs[] = { + 0x9004, /* GPU_CC_CXO_AON_CLK */ + 0x900c, /* GPU_CC_DEMET_CLK */ +}; + +static const struct regmap_config gpu_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9988, + .fast_io = true, +}; + +static struct qcom_cc_driver_data gpu_cc_eliza_driver_data = { + .alpha_plls = gpu_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(gpu_cc_eliza_plls), + .clk_cbcrs = gpu_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc gpu_cc_eliza_desc = { + .config = &gpu_cc_eliza_regmap_config, + .clks = gpu_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_eliza_clocks), + .resets = gpu_cc_eliza_resets, + .num_resets = ARRAY_SIZE(gpu_cc_eliza_resets), + .gdscs = gpu_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_eliza_gdscs), + .use_rpm = true, + .driver_data = &gpu_cc_eliza_driver_data, +}; + +static const struct of_device_id gpu_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_eliza_match_table); + +static int gpu_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &gpu_cc_eliza_desc); +} + +static struct platform_driver gpu_cc_eliza_driver = { + .probe = gpu_cc_eliza_probe, + .driver = { + .name = "gpucc-eliza", + .of_match_table = gpu_cc_eliza_match_table, + }, +}; + +module_platform_driver(gpu_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI GPUCC Eliza Driver"); +MODULE_LICENSE("GPL"); From dcf6518b860209e2608f9cb22081f829ab7b43d4 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 9 Jun 2026 20:32:57 +0530 Subject: [PATCH 0653/1058] FROMLIST: clk: qcom: camcc: Add support for camera clock controller for Eliza Add support for the Camera Clock Controller (CAMCC) on the Eliza platform. The CAMCC block on Eliza includes both the primary camera clock controller and the Camera BIST clock controller, which provides the functional MCLK required for camera operations. Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260609-b4-eliza_mm_cc_v6-v6-6-17df09e5940c@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 11 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/cambistmclkcc-eliza.c | 465 ++++ drivers/clk/qcom/camcc-eliza.c | 2803 ++++++++++++++++++++++++ 4 files changed, 3280 insertions(+) create mode 100644 drivers/clk/qcom/cambistmclkcc-eliza.c create mode 100644 drivers/clk/qcom/camcc-eliza.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 80f4a7e0ccde3..694b396a49f0b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -19,6 +19,17 @@ menuconfig COMMON_CLK_QCOM if COMMON_CLK_QCOM +config CLK_ELIZA_CAMCC + tristate "Eliza Camera Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the camera clock controller on Qualcomm Technologies, Inc + Eliza devices. + Say Y if you want to support camera devices and functionality such as + capturing pictures. + config CLK_ELIZA_DISPCC tristate "Eliza Display Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 0bbc792492178..68311957d4d40 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -20,6 +20,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o # Keep alphabetically sorted by config obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o +obj-$(CONFIG_CLK_ELIZA_CAMCC) += cambistmclkcc-eliza.o camcc-eliza.o obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o diff --git a/drivers/clk/qcom/cambistmclkcc-eliza.c b/drivers/clk/qcom/cambistmclkcc-eliza.c new file mode 100644 index 0000000000000..b65e224a1be90 --- /dev/null +++ b/drivers/clk/qcom/cambistmclkcc-eliza.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, + P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco rivian_ole_vco[] = { + { 777000000, 1285000000, 0 }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_bist_mclk_cc_pll0_config = { + .l = 0x32, + .cal_l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x10000030, + .config_ctl_hi_val = 0x80890263, + .config_ctl_hi1_val = 0x00000217, + .user_ctl_val = 0x00000001, + .user_ctl_hi_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_bist_mclk_cc_pll0 = { + .offset = 0x0, + .config = &cam_bist_mclk_cc_pll0_config, + .vco_table = rivian_ole_vco, + .num_vco = ARRAY_SIZE(rivian_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_rivian_evo_ops, + }, + }, +}; + +static const struct parent_map cam_bist_mclk_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 3 }, + { P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_bist_mclk_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_bist_mclk_cc_pll0.clkr.hw }, + { .hw = &cam_bist_mclk_cc_pll0.clkr.hw }, +}; + +static const struct parent_map cam_bist_mclk_cc_parent_map_1[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_bist_mclk_cc_parent_data_1[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_cam_bist_mclk_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 10, 1, 4), + F(68571429, P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 14, 0, 0), + { } +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk0_clk_src = { + .cmd_rcgr = 0x4000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk0_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk1_clk_src = { + .cmd_rcgr = 0x401c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk1_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk2_clk_src = { + .cmd_rcgr = 0x4038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk2_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk3_clk_src = { + .cmd_rcgr = 0x4054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk3_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk4_clk_src = { + .cmd_rcgr = 0x4070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk4_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk5_clk_src = { + .cmd_rcgr = 0x408c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk5_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk6_clk_src = { + .cmd_rcgr = 0x40a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk6_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk7_clk_src = { + .cmd_rcgr = 0x40c4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk7_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_bist_mclk_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_bist_mclk_cc_sleep_clk_src = { + .cmd_rcgr = 0x40e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_1, + .freq_tbl = ftbl_cam_bist_mclk_cc_sleep_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_sleep_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk0_clk = { + .halt_reg = 0x4018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk1_clk = { + .halt_reg = 0x4034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk2_clk = { + .halt_reg = 0x4050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk3_clk = { + .halt_reg = 0x406c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x406c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk4_clk = { + .halt_reg = 0x4088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk5_clk = { + .halt_reg = 0x40a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk6_clk = { + .halt_reg = 0x40c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk7_clk = { + .halt_reg = 0x40dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk7_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *cam_bist_mclk_cc_eliza_clocks[] = { + [CAM_BIST_MCLK_CC_MCLK0_CLK] = &cam_bist_mclk_cc_mclk0_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK0_CLK_SRC] = &cam_bist_mclk_cc_mclk0_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK1_CLK] = &cam_bist_mclk_cc_mclk1_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK1_CLK_SRC] = &cam_bist_mclk_cc_mclk1_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK2_CLK] = &cam_bist_mclk_cc_mclk2_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK2_CLK_SRC] = &cam_bist_mclk_cc_mclk2_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK3_CLK] = &cam_bist_mclk_cc_mclk3_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK3_CLK_SRC] = &cam_bist_mclk_cc_mclk3_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK4_CLK] = &cam_bist_mclk_cc_mclk4_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK4_CLK_SRC] = &cam_bist_mclk_cc_mclk4_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK5_CLK] = &cam_bist_mclk_cc_mclk5_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK5_CLK_SRC] = &cam_bist_mclk_cc_mclk5_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK6_CLK] = &cam_bist_mclk_cc_mclk6_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK6_CLK_SRC] = &cam_bist_mclk_cc_mclk6_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK7_CLK] = &cam_bist_mclk_cc_mclk7_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK7_CLK_SRC] = &cam_bist_mclk_cc_mclk7_clk_src.clkr, + [CAM_BIST_MCLK_CC_PLL0] = &cam_bist_mclk_cc_pll0.clkr, + [CAM_BIST_MCLK_CC_SLEEP_CLK_SRC] = &cam_bist_mclk_cc_sleep_clk_src.clkr, +}; + +static struct clk_alpha_pll *cam_bist_mclk_cc_eliza_plls[] = { + &cam_bist_mclk_cc_pll0, +}; + +static u32 cam_bist_mclk_cc_eliza_critical_cbcrs[] = { + 0x40f8, /* CAM_BIST_MCLK_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_bist_mclk_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x5010, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_bist_mclk_cc_eliza_driver_data = { + .alpha_plls = cam_bist_mclk_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(cam_bist_mclk_cc_eliza_plls), + .clk_cbcrs = cam_bist_mclk_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_bist_mclk_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_bist_mclk_cc_eliza_desc = { + .config = &cam_bist_mclk_cc_eliza_regmap_config, + .clks = cam_bist_mclk_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(cam_bist_mclk_cc_eliza_clocks), + .use_rpm = true, + .driver_data = &cam_bist_mclk_cc_eliza_driver_data, +}; + +static const struct of_device_id cam_bist_mclk_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-cambistmclkcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_bist_mclk_cc_eliza_match_table); + +static int cam_bist_mclk_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_bist_mclk_cc_eliza_desc); +} + +static struct platform_driver cam_bist_mclk_cc_eliza_driver = { + .probe = cam_bist_mclk_cc_eliza_probe, + .driver = { + .name = "cambistmclkcc-eliza", + .of_match_table = cam_bist_mclk_cc_eliza_match_table, + }, +}; + +module_platform_driver(cam_bist_mclk_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI CAMBISTMCLKCC Eliza Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/camcc-eliza.c b/drivers/clk/qcom/camcc-eliza.c new file mode 100644 index 0000000000000..b96a2a58b32a7 --- /dev/null +++ b/drivers/clk/qcom/camcc-eliza.c @@ -0,0 +1,2803 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EVEN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_CAM_CC_PLL5_OUT_EVEN, + P_CAM_CC_PLL6_OUT_EVEN, + P_CAM_CC_PLL6_OUT_ODD, + P_SLEEP_CLK, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 1200.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .cal_l = 0x44, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00008400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .config = &cam_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 900.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0xe000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .config = &cam_cc_pll1_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 872.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x2d, + .cal_l = 0x44, + .alpha = 0x6aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .config = &cam_cc_pll2_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll2_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll2_out_even = { + .offset = 0x2000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll2_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .config = &cam_cc_pll3_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .config = &cam_cc_pll4_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll5_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll5 = { + .offset = 0x5000, + .config = &cam_cc_pll5_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = { + .offset = 0x5000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll5_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll5.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll6_config = { + .l = 0x32, + .cal_l = 0x44, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00008400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll6 = { + .offset = 0x6000, + .config = &cam_cc_pll6_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = { + .offset = 0x6000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll6_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll6.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll6_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll6_out_odd = { + .offset = 0x6000, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll6_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll6.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL6_OUT_ODD, 4 }, + { P_CAM_CC_PLL6_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL6_OUT_ODD, 4 }, + { P_CAM_CC_PLL6_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll2_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL5_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll5_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_8[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_8[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_rt_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_rt_axi_clk_src = { + .cmd_rcgr = 0x112e8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_rt_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_axi_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0x1126c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0x11288, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_2_clk_src = { + .cmd_rcgr = 0x112a4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x11068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = { + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cre_clk_src = { + .cmd_rcgr = 0x111ac, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cre_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x10000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x10024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x10044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi2phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x10064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi3phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x10084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .cmd_rcgr = 0x100a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi5phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csid_clk_src = { + .cmd_rcgr = 0x112c0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x100dc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_0_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_0_clk_src = { + .cmd_rcgr = 0x11214, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_icp_1_clk_src = { + .cmd_rcgr = 0x1123c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0x11150, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0x1117c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = { + F(450000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_nps_clk_src = { + .cmd_rcgr = 0x10190, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0x111d0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cre_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ofe_clk_src[] = { + F(436000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(570000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(757000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ofe_clk_src = { + .cmd_rcgr = 0x1011c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ofe_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = { + F(60000000, P_CAM_CC_PLL6_OUT_EVEN, 8, 0, 0), + F(120000000, P_CAM_CC_PLL0_OUT_EVEN, 5, 0, 0), + F(240000000, P_CAM_CC_PLL0_OUT_MAIN, 5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_qdss_debug_clk_src = { + .cmd_rcgr = 0x1132c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0x11380, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x10100, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_0_clk_src[] = { + F(445000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_0_clk_src = { + .cmd_rcgr = 0x11018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_1_clk_src[] = { + F(445000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_1_clk_src = { + .cmd_rcgr = 0x11098, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_tfe_1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_clk_src", + .parent_data = cam_cc_parent_data_6, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_2_clk_src[] = { + F(445000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_2_clk_src = { + .cmd_rcgr = 0x11100, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_7, + .freq_tbl = ftbl_cam_cc_tfe_2_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_clk_src", + .parent_data = cam_cc_parent_data_7, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0x11364, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_8, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_8, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch cam_cc_cam_top_ahb_clk = { + .halt_reg = 0x113ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cam_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cam_top_fast_ahb_clk = { + .halt_reg = 0x1139c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1139c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cam_top_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0x11320, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11320, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_axi_clk = { + .halt_reg = 0x11310, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x11310, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x11310, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_rt_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_cre_clk = { + .halt_reg = 0x111c8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111c8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ipe_nps_clk = { + .halt_reg = 0x101b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101b8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_anchor_clk = { + .halt_reg = 0x10158, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10158, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_anchor_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_hdr_clk = { + .halt_reg = 0x1016c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1016c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_hdr_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_main_clk = { + .halt_reg = 0x10144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_axi_clk = { + .halt_reg = 0x11300, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11300, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_rt_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_ife_lite_clk = { + .halt_reg = 0x11178, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11178, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_0_bayer_clk = { + .halt_reg = 0x11054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_0_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_0_main_clk = { + .halt_reg = 0x11040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_0_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_1_bayer_clk = { + .halt_reg = 0x110d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_1_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_1_main_clk = { + .halt_reg = 0x110c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_1_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_2_bayer_clk = { + .halt_reg = 0x1113c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1113c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_2_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_2_main_clk = { + .halt_reg = 0x11128, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11128, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_2_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_xo_clk = { + .halt_reg = 0x11324, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11324, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0x11284, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11284, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0x112a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_2_clk = { + .halt_reg = 0x112bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0x11360, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x11360, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cre_ahb_clk = { + .halt_reg = 0x111cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cre_clk = { + .halt_reg = 0x111c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x1003c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1003c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi2phytimer_clk = { + .halt_reg = 0x1005c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1005c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi2phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi3phytimer_clk = { + .halt_reg = 0x1007c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1007c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi3phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi3phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x1009c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1009c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi4phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi5phytimer_clk = { + .halt_reg = 0x100bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi5phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi5phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_clk = { + .halt_reg = 0x112d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_csiphy_rx_clk = { + .halt_reg = 0x10020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_csiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x1001c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x10040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy2_clk = { + .halt_reg = 0x10060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy3_clk = { + .halt_reg = 0x10080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x100a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy5_clk = { + .halt_reg = 0x100c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_drv_ahb_clk = { + .halt_reg = 0x113c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch cam_cc_drv_xo_clk = { + .halt_reg = 0x113c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_0_ahb_clk = { + .halt_reg = 0x11264, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11264, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_0_clk = { + .halt_reg = 0x1122c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1122c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_1_ahb_clk = { + .halt_reg = 0x11268, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11268, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_1_clk = { + .halt_reg = 0x11254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0x111a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0x11168, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11168, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0x111a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0x11194, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11194, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_ahb_clk = { + .halt_reg = 0x101d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_clk = { + .halt_reg = 0x101a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = { + .halt_reg = 0x101d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_clk = { + .halt_reg = 0x101bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = { + .halt_reg = 0x101dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_0_clk = { + .halt_reg = 0x111e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111e8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_1_clk = { + .halt_reg = 0x111f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_ahb_clk = { + .halt_reg = 0x10118, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10118, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_anchor_clk = { + .halt_reg = 0x10148, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_anchor_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_anchor_fast_ahb_clk = { + .halt_reg = 0x100f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_anchor_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_hdr_clk = { + .halt_reg = 0x1015c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1015c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_hdr_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_hdr_fast_ahb_clk = { + .halt_reg = 0x100fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_hdr_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_main_clk = { + .halt_reg = 0x10134, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10134, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_main_fast_ahb_clk = { + .halt_reg = 0x100f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_clk = { + .halt_reg = 0x11344, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11344, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_qdss_debug_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_xo_clk = { + .halt_reg = 0x11348, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11348, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_bayer_clk = { + .halt_reg = 0x11044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_bayer_fast_ahb_clk = { + .halt_reg = 0x11064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_main_clk = { + .halt_reg = 0x11030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_main_fast_ahb_clk = { + .halt_reg = 0x11060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_bayer_clk = { + .halt_reg = 0x110c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_bayer_fast_ahb_clk = { + .halt_reg = 0x110e4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110e4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_main_clk = { + .halt_reg = 0x110b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_main_fast_ahb_clk = { + .halt_reg = 0x110e0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_bayer_clk = { + .halt_reg = 0x1112c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1112c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_bayer_fast_ahb_clk = { + .halt_reg = 0x1114c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1114c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_main_clk = { + .halt_reg = 0x11118, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11118, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_main_fast_ahb_clk = { + .halt_reg = 0x11148, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc cam_cc_titan_top_gdsc = { + .gdscr = 0x1134c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ipe_0_gdsc = { + .gdscr = 0x1017c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ipe_0_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ofe_gdsc = { + .gdscr = 0x100c8, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ofe_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_0_gdsc = { + .gdscr = 0x11004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_0_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_1_gdsc = { + .gdscr = 0x11084, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_1_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_2_gdsc = { + .gdscr = 0x110ec, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_2_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *cam_cc_eliza_clocks[] = { + [CAM_CC_CAM_TOP_AHB_CLK] = &cam_cc_cam_top_ahb_clk.clkr, + [CAM_CC_CAM_TOP_FAST_AHB_CLK] = &cam_cc_cam_top_fast_ahb_clk.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CAMNOC_NRT_AXI_CLK] = &cam_cc_camnoc_nrt_axi_clk.clkr, + [CAM_CC_CAMNOC_NRT_CRE_CLK] = &cam_cc_camnoc_nrt_cre_clk.clkr, + [CAM_CC_CAMNOC_NRT_IPE_NPS_CLK] = &cam_cc_camnoc_nrt_ipe_nps_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK] = &cam_cc_camnoc_nrt_ofe_anchor_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_HDR_CLK] = &cam_cc_camnoc_nrt_ofe_hdr_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK] = &cam_cc_camnoc_nrt_ofe_main_clk.clkr, + [CAM_CC_CAMNOC_RT_AXI_CLK] = &cam_cc_camnoc_rt_axi_clk.clkr, + [CAM_CC_CAMNOC_RT_AXI_CLK_SRC] = &cam_cc_camnoc_rt_axi_clk_src.clkr, + [CAM_CC_CAMNOC_RT_IFE_LITE_CLK] = &cam_cc_camnoc_rt_ife_lite_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_0_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_0_main_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_1_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_1_main_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_2_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_2_main_clk.clkr, + [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr, + [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr, + [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr, + [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr, + [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr, + [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr, + [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr, + [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr, + [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr, + [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr, + [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr, + [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr, + [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr, + [CAM_CC_DRV_XO_CLK] = &cam_cc_drv_xo_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_ICP_0_AHB_CLK] = &cam_cc_icp_0_ahb_clk.clkr, + [CAM_CC_ICP_0_CLK] = &cam_cc_icp_0_clk.clkr, + [CAM_CC_ICP_0_CLK_SRC] = &cam_cc_icp_0_clk_src.clkr, + [CAM_CC_ICP_1_AHB_CLK] = &cam_cc_icp_1_ahb_clk.clkr, + [CAM_CC_ICP_1_CLK] = &cam_cc_icp_1_clk.clkr, + [CAM_CC_ICP_1_CLK_SRC] = &cam_cc_icp_1_clk_src.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr, + [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr, + [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr, + [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr, + [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr, + [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr, + [CAM_CC_JPEG_0_CLK] = &cam_cc_jpeg_0_clk.clkr, + [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_OFE_AHB_CLK] = &cam_cc_ofe_ahb_clk.clkr, + [CAM_CC_OFE_ANCHOR_CLK] = &cam_cc_ofe_anchor_clk.clkr, + [CAM_CC_OFE_ANCHOR_FAST_AHB_CLK] = &cam_cc_ofe_anchor_fast_ahb_clk.clkr, + [CAM_CC_OFE_CLK_SRC] = &cam_cc_ofe_clk_src.clkr, + [CAM_CC_OFE_HDR_CLK] = &cam_cc_ofe_hdr_clk.clkr, + [CAM_CC_OFE_HDR_FAST_AHB_CLK] = &cam_cc_ofe_hdr_fast_ahb_clk.clkr, + [CAM_CC_OFE_MAIN_CLK] = &cam_cc_ofe_main_clk.clkr, + [CAM_CC_OFE_MAIN_FAST_AHB_CLK] = &cam_cc_ofe_main_fast_ahb_clk.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL2_OUT_EVEN] = &cam_cc_pll2_out_even.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_PLL5] = &cam_cc_pll5.clkr, + [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr, + [CAM_CC_PLL6] = &cam_cc_pll6.clkr, + [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr, + [CAM_CC_PLL6_OUT_ODD] = &cam_cc_pll6_out_odd.clkr, + [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr, + [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr, + [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_TFE_0_BAYER_CLK] = &cam_cc_tfe_0_bayer_clk.clkr, + [CAM_CC_TFE_0_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_0_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_0_CLK_SRC] = &cam_cc_tfe_0_clk_src.clkr, + [CAM_CC_TFE_0_MAIN_CLK] = &cam_cc_tfe_0_main_clk.clkr, + [CAM_CC_TFE_0_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_0_main_fast_ahb_clk.clkr, + [CAM_CC_TFE_1_BAYER_CLK] = &cam_cc_tfe_1_bayer_clk.clkr, + [CAM_CC_TFE_1_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_1_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_1_CLK_SRC] = &cam_cc_tfe_1_clk_src.clkr, + [CAM_CC_TFE_1_MAIN_CLK] = &cam_cc_tfe_1_main_clk.clkr, + [CAM_CC_TFE_1_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_1_main_fast_ahb_clk.clkr, + [CAM_CC_TFE_2_BAYER_CLK] = &cam_cc_tfe_2_bayer_clk.clkr, + [CAM_CC_TFE_2_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_2_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_2_CLK_SRC] = &cam_cc_tfe_2_clk_src.clkr, + [CAM_CC_TFE_2_MAIN_CLK] = &cam_cc_tfe_2_main_clk.clkr, + [CAM_CC_TFE_2_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_2_main_fast_ahb_clk.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_eliza_gdscs[] = { + [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc, + [CAM_CC_OFE_GDSC] = &cam_cc_ofe_gdsc, + [CAM_CC_TFE_0_GDSC] = &cam_cc_tfe_0_gdsc, + [CAM_CC_TFE_1_GDSC] = &cam_cc_tfe_1_gdsc, + [CAM_CC_TFE_2_GDSC] = &cam_cc_tfe_2_gdsc, + [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_eliza_resets[] = { + [CAM_CC_DRV_BCR] = { 0x113bc }, + [CAM_CC_ICP_BCR] = { 0x11210 }, + [CAM_CC_IPE_0_BCR] = { 0x10178 }, + [CAM_CC_OFE_BCR] = { 0x100c4 }, + [CAM_CC_QDSS_DEBUG_BCR] = { 0x11328 }, + [CAM_CC_TFE_0_BCR] = { 0x11000 }, + [CAM_CC_TFE_1_BCR] = { 0x11080 }, + [CAM_CC_TFE_2_BCR] = { 0x110e8 }, +}; + +static struct clk_alpha_pll *cam_cc_eliza_plls[] = { + &cam_cc_pll0, + &cam_cc_pll1, + &cam_cc_pll2, + &cam_cc_pll3, + &cam_cc_pll4, + &cam_cc_pll5, + &cam_cc_pll6, +}; + +static u32 cam_cc_eliza_critical_cbcrs[] = { + 0x1137c, /* CAM_CC_GDSC_CLK */ + 0x11398, /* CAM_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1601c, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_cc_eliza_driver_data = { + .alpha_plls = cam_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(cam_cc_eliza_plls), + .clk_cbcrs = cam_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_cc_eliza_desc = { + .config = &cam_cc_eliza_regmap_config, + .clks = cam_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(cam_cc_eliza_clocks), + .resets = cam_cc_eliza_resets, + .num_resets = ARRAY_SIZE(cam_cc_eliza_resets), + .gdscs = cam_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_eliza_gdscs), + .driver_data = &cam_cc_eliza_driver_data, +}; + +static const struct of_device_id cam_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_eliza_match_table); + +static int cam_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_cc_eliza_desc); +} + +static struct platform_driver cam_cc_eliza_driver = { + .probe = cam_cc_eliza_probe, + .driver = { + .name = "camcc-eliza", + .of_match_table = cam_cc_eliza_match_table, + }, +}; + +module_platform_driver(cam_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI CAMCC Eliza Driver"); +MODULE_LICENSE("GPL"); From 06ad955aee9456246789ddfb0bd923706c068a3d Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 3 Mar 2026 14:46:00 +0530 Subject: [PATCH 0654/1058] dt-bindings: firmware: qcom,scm: Document SCM on Shikra SoC Document the SCM compatible on the Shikra SoC. Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 25f62bacbc919..aa2b2d4fe71b3 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -67,6 +67,7 @@ properties: - qcom,scm-sdx55 - qcom,scm-sdx65 - qcom,scm-sdx75 + - qcom,scm-shikra - qcom,scm-sm6115 - qcom,scm-sm6125 - qcom,scm-sm6350 From d6276f34318c3285ec76ff92342bcb614c38a896 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 3 Mar 2026 16:11:55 +0530 Subject: [PATCH 0655/1058] dt-bindings: arm: qcom: Document Shikra and its evk boards Document the device tree binding for the Shikra EVK platform, which is built around a modular System-on-Module (SoM) mounted on a common carrier board. The SoM integrates the Shikra SoC, PMICs, and essential GPIOs, while the EVK carrier board provides additional peripherals such as UART and USB interfaces. Shikra EVK supports three SoM variants: retail with modem, retail without modem, and an industrial non-modem variant. Signed-off-by: Komal Bajaj --- .../devicetree/bindings/arm/qcom.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 50cc18a6ec5ed..73a7878281b94 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -968,6 +968,24 @@ properties: - const: qcom,qcs9100 - const: qcom,sa8775p + - items: + - enum: + - qcom,shikra-cqm-evk + - const: qcom,shikra-cqm-som + - const: qcom,shikra + + - items: + - enum: + - qcom,shikra-cqs-evk + - const: qcom,shikra-cqs-som + - const: qcom,shikra + + - items: + - enum: + - qcom,shikra-iqs-evk + - const: qcom,shikra-iqs-som + - const: qcom,shikra + - items: - enum: - google,blueline From 7c3865bc2efe4bcd420afbf419b2b5749dfc9d80 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 4 Mar 2026 12:39:18 +0530 Subject: [PATCH 0656/1058] dt-bindings: sram: qcom,imem: Add the Shikra compatible Add compatible for Shikra SoC IMEM. Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/sram/qcom,imem.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index c63026904061d..2eb7566afef38 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -36,6 +36,7 @@ properties: - qcom,sdx55-imem - qcom,sdx65-imem - qcom,sdx75-imem + - qcom,shikra-imem - qcom,sm6115-imem - qcom,sm6125-imem - qcom,sm6350-imem From 8d1d3c5603ed05ba8a5015cb939edd6d1dadd38a Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Fri, 6 Mar 2026 15:53:10 +0530 Subject: [PATCH 0657/1058] soc: qcom: rpmpd: Add Shikra RPM support Shikra has the same RPM power domains as QCM2290. Add shikra support by reusing QCM2290 power domains. Signed-off-by: Rakesh Kota --- drivers/pmdomain/qcom/rpmpd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c index 5f55fc791131a..335185830cf38 100644 --- a/drivers/pmdomain/qcom/rpmpd.c +++ b/drivers/pmdomain/qcom/rpmpd.c @@ -863,6 +863,21 @@ static const struct rpmpd_desc sdm660_desc = { .max_state = RPM_SMD_LEVEL_TURBO, }; +static struct rpmpd *shikra_rpmpds[] = { + [RPMPD_VDDCX] = &cx_rwcx0_lvl, + [RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao, + [RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl, + [RPMPD_VDDMX] = &mx_rwmx0_lvl, + [RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao, + [RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl, +}; + +static const struct rpmpd_desc shikra_desc = { + .rpmpds = shikra_rpmpds, + .num_pds = ARRAY_SIZE(shikra_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static struct rpmpd *sm6115_rpmpds[] = { [SM6115_VDDCX] = &cx_rwcx0_lvl, [SM6115_VDDCX_AO] = &cx_rwcx0_lvl_ao, From 8dcfaa854dacb97d96c049909631438797eeb786 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 26 Mar 2026 15:11:01 +0530 Subject: [PATCH 0658/1058] dt-bindings: arm-smmu: Add adreno-smmu compatible for Shikra SoC Qualcomm Shikra SoC implements qcom,smmu-500 for adreno-smmu. Document its corresponding compatible. Signed-off-by: Bibek Kumar Patro --- Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index a701dec2fa0a4..9c0f298719cdf 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -108,6 +108,7 @@ properties: - qcom,sc7280-smmu-500 - qcom,sc8180x-smmu-500 - qcom,sc8280xp-smmu-500 + - qcom,shikra-smmu-500 - qcom,sm6115-smmu-500 - qcom,sm6125-smmu-500 - qcom,sm8150-smmu-500 From a8b28f95f24284be21bca6eba13e65d2ed2d974a Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 27 Jan 2026 13:43:04 +0530 Subject: [PATCH 0659/1058] mailbox: qcom-apcs-ipc-mailbox: Add compatible string Add "qcom,shikra-apcs-hmss-global" compatibility string in qcom_apcs_ipc mailbox driver to match apcs_glb device node. Signed-off-by: Vishnu Santhosh --- drivers/mailbox/qcom-apcs-ipc-mailbox.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c index d3a8f6b4a03b3..8e544dbe3c5ff 100644 --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c @@ -168,6 +168,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = { { .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq6018_apcs_data }, { .compatible = "qcom,sc7180-apss-shared", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sc8180x-apss-shared", .data = &apps_shared_apcs_data }, + { .compatible = "qcom,shikra-apcs-hmss-global", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data }, {} }; From 44a25aaae34382f2cb76f20a6a08f619df78db31 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 27 Mar 2026 17:17:17 +0530 Subject: [PATCH 0660/1058] dt-bindings: nvmem: qfprom: Add Shikra compatible Document compatible string for the QFPROM on Shikra platform. Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml index 2ab047f2bb69d..52b86133ee00d 100644 --- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml +++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml @@ -48,6 +48,7 @@ properties: - qcom,sdm630-qfprom - qcom,sdm670-qfprom - qcom,sdm845-qfprom + - qcom,shikra-qfprom - qcom,sm6115-qfprom - qcom,sm6350-qfprom - qcom,sm6375-qfprom From 837779c06723150f7d7171db1fef005101ad32be Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 27 Mar 2026 18:14:37 +0530 Subject: [PATCH 0661/1058] dt-bindings: mailbox: qcom: Add the Shikra APCS compatible Add compatible for the Qualcomm Shikra APCS block to the Qualcomm APCS binding. Signed-off-by: Sneh Mankad Signed-off-by: Komal Bajaj --- .../devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml index 1b4ef0688ca79..01d6eaefe165e 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml @@ -66,6 +66,7 @@ properties: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global reg: maxItems: 1 @@ -239,6 +240,7 @@ allOf: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global then: properties: clocks: false From e3ba73ebe17284ce2f8fa20c1529f05e9c2671ae Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 27 Mar 2026 18:19:38 +0530 Subject: [PATCH 0662/1058] dt-bindings: soc: qcom: qcom,smd-rpm: Add compatible for Shikra Document the compatible for Shikra. Signed-off-by: Sneh Mankad Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index 270bcd079f886..bd1d32898461c 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -57,6 +57,7 @@ properties: - qcom,rpm-qcm2290 - qcom,rpm-qcs404 - qcom,rpm-sdm660 + - qcom,rpm-shikra - qcom,rpm-sm6115 - qcom,rpm-sm6125 - qcom,rpm-sm6375 From 0ea8a2b2e2524e509ede49ec35e212ec4b42413e Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 19:17:43 +0530 Subject: [PATCH 0663/1058] dt-bindings: clock: qcom,rpmcc: Add Shikra compatible Document the qcom,rpmcc-shikra compatible. Signed-off-by: Imran Shaik --- Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml index ab97d4b7dba8b..06f8439bb032a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml @@ -46,6 +46,7 @@ properties: - qcom,rpmcc-qcs404 - qcom,rpmcc-sdm429 - qcom,rpmcc-sdm660 + - qcom,rpmcc-shikra - qcom,rpmcc-sm6115 - qcom,rpmcc-sm6125 - qcom,rpmcc-sm6375 From 9f3a74f42fddac55f1bd295c5379c541b734f1a7 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 18:38:09 +0530 Subject: [PATCH 0664/1058] dt-bindings: clock: qcom: Add GCC clocks for Shikra Add support for qcom global clock controller bindings for Shikra platform. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,shikra-gcc.yaml | 63 +++++ include/dt-bindings/clock/qcom,shikra-gcc.h | 258 ++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml create mode 100644 include/dt-bindings/clock/qcom,shikra-gcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml new file mode 100644 index 0000000000000..39cf7383df8bc --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,shikra-gcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller on Shikra + +maintainers: + - Imran Shaik + - Taniya Das + +description: | + Qualcomm global clock control module provides the clocks, resets and power + domains on Shikra. + + See also: include/dt-bindings/clock/qcom,shikra-gcc.h + +properties: + compatible: + const: qcom,shikra-gcc + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: EMAC0 sgmiiphy mac rclk source + - description: EMAC0 sgmiiphy mac tclk source + - description: EMAC1 sgmiiphy mac rclk source + - description: EMAC1 sgmiiphy mac tclk source + - description: PCIE Pipe clock source + - description: USB3 phy wrapper pipe clock source + +required: + - compatible + - clocks + - '#power-domain-cells' + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + clock-controller@1400000 { + compatible = "qcom,shikra-gcc"; + reg = <0x01400000 0x1f0000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&emac0_sgmiiphy_rclk>, + <&emac0_sgmiiphy_tclk>, + <&emac1_sgmiiphy_rclk>, + <&emac1_sgmiiphy_tclk>, + <&pcie_pipe_clk>, + <&usb3_phy_wrapper_gcc_usb30_pipe_clk>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/qcom,shikra-gcc.h b/include/dt-bindings/clock/qcom,shikra-gcc.h new file mode 100644 index 0000000000000..77c6159755ce9 --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-gcc.h @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SHIKRA_H + +/* GCC clocks */ +#define GPLL0 0 +#define GPLL0_OUT_AUX2 1 +#define GPLL1 2 +#define GPLL10 3 +#define GPLL11 4 +#define GPLL12 5 +#define GPLL12_OUT_AUX2 6 +#define GPLL3 7 +#define GPLL3_OUT_MAIN 8 +#define GPLL4 9 +#define GPLL5 10 +#define GPLL6 11 +#define GPLL6_OUT_MAIN 12 +#define GPLL7 13 +#define GPLL8 14 +#define GPLL8_OUT_MAIN 15 +#define GPLL9 16 +#define GPLL9_OUT_MAIN 17 +#define GCC_AHB2PHY_CSI_CLK 18 +#define GCC_AHB2PHY_USB_CLK 19 +#define GCC_BOOT_ROM_AHB_CLK 20 +#define GCC_CAM_THROTTLE_NRT_CLK 21 +#define GCC_CAM_THROTTLE_RT_CLK 22 +#define GCC_CAMERA_AHB_CLK 23 +#define GCC_CAMERA_XO_CLK 24 +#define GCC_CAMSS_AXI_CLK 25 +#define GCC_CAMSS_AXI_CLK_SRC 26 +#define GCC_CAMSS_CAMNOC_ATB_CLK 27 +#define GCC_CAMSS_CAMNOC_DRAGONLINK_ATB_CLK 28 +#define GCC_CAMSS_CAMNOC_NTS_XO_CLK 29 +#define GCC_CAMSS_CCI_0_CLK 30 +#define GCC_CAMSS_CCI_CLK_SRC 31 +#define GCC_CAMSS_CPHY_0_CLK 32 +#define GCC_CAMSS_CPHY_1_CLK 33 +#define GCC_CAMSS_CSI0PHYTIMER_CLK 34 +#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC 35 +#define GCC_CAMSS_CSI1PHYTIMER_CLK 36 +#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC 37 +#define GCC_CAMSS_MCLK0_CLK 38 +#define GCC_CAMSS_MCLK0_CLK_SRC 39 +#define GCC_CAMSS_MCLK1_CLK 40 +#define GCC_CAMSS_MCLK1_CLK_SRC 41 +#define GCC_CAMSS_MCLK2_CLK 42 +#define GCC_CAMSS_MCLK2_CLK_SRC 43 +#define GCC_CAMSS_MCLK3_CLK 44 +#define GCC_CAMSS_MCLK3_CLK_SRC 45 +#define GCC_CAMSS_NRT_AXI_CLK 46 +#define GCC_CAMSS_OPE_AHB_CLK 47 +#define GCC_CAMSS_OPE_AHB_CLK_SRC 48 +#define GCC_CAMSS_OPE_CLK 49 +#define GCC_CAMSS_OPE_CLK_SRC 50 +#define GCC_CAMSS_RT_AXI_CLK 51 +#define GCC_CAMSS_TFE_0_CLK 52 +#define GCC_CAMSS_TFE_0_CLK_SRC 53 +#define GCC_CAMSS_TFE_0_CPHY_RX_CLK 54 +#define GCC_CAMSS_TFE_0_CSID_CLK 55 +#define GCC_CAMSS_TFE_0_CSID_CLK_SRC 56 +#define GCC_CAMSS_TFE_1_CLK 57 +#define GCC_CAMSS_TFE_1_CLK_SRC 58 +#define GCC_CAMSS_TFE_1_CPHY_RX_CLK 59 +#define GCC_CAMSS_TFE_1_CSID_CLK 60 +#define GCC_CAMSS_TFE_1_CSID_CLK_SRC 61 +#define GCC_CAMSS_TFE_CPHY_RX_CLK_SRC 62 +#define GCC_CAMSS_TOP_AHB_CLK 63 +#define GCC_CAMSS_TOP_AHB_CLK_SRC 64 +#define GCC_CFG_NOC_USB2_PRIM_AXI_CLK 65 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 66 +#define GCC_DDRSS_GPU_AXI_CLK 67 +#define GCC_DDRSS_MEMNOC_PCIE_SF_CLK 68 +#define GCC_DISP_AHB_CLK 69 +#define GCC_DISP_GPLL0_CLK_SRC 70 +#define GCC_DISP_GPLL0_DIV_CLK_SRC 71 +#define GCC_DISP_HF_AXI_CLK 72 +#define GCC_DISP_THROTTLE_CORE_CLK 73 +#define GCC_DISP_XO_CLK 74 +#define GCC_EMAC0_AHB_CLK 75 +#define GCC_EMAC0_AXI_CLK 76 +#define GCC_EMAC0_AXI_CLK_SRC 77 +#define GCC_EMAC0_AXI_SYS_NOC_CLK 78 +#define GCC_EMAC0_CC_SGMIIPHY_RX_CLK 79 +#define GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC 80 +#define GCC_EMAC0_CC_SGMIIPHY_TX_CLK 81 +#define GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC 82 +#define GCC_EMAC0_PHY_AUX_CLK 83 +#define GCC_EMAC0_PHY_AUX_CLK_SRC 84 +#define GCC_EMAC0_PTP_CLK 85 +#define GCC_EMAC0_PTP_CLK_SRC 86 +#define GCC_EMAC0_RGMII_CLK 87 +#define GCC_EMAC0_RGMII_CLK_SRC 88 +#define GCC_EMAC1_AHB_CLK 89 +#define GCC_EMAC1_AXI_CLK 90 +#define GCC_EMAC1_AXI_CLK_SRC 91 +#define GCC_EMAC1_AXI_SYS_NOC_CLK 92 +#define GCC_EMAC1_CC_SGMIIPHY_RX_CLK 93 +#define GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC 94 +#define GCC_EMAC1_CC_SGMIIPHY_TX_CLK 95 +#define GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC 96 +#define GCC_EMAC1_PHY_AUX_CLK 97 +#define GCC_EMAC1_PHY_AUX_CLK_SRC 98 +#define GCC_EMAC1_PTP_CLK 99 +#define GCC_EMAC1_PTP_CLK_SRC 100 +#define GCC_EMAC1_RGMII_CLK 101 +#define GCC_EMAC1_RGMII_CLK_SRC 102 +#define GCC_GP1_CLK 103 +#define GCC_GP1_CLK_SRC 104 +#define GCC_GP2_CLK 105 +#define GCC_GP2_CLK_SRC 106 +#define GCC_GP3_CLK 107 +#define GCC_GP3_CLK_SRC 108 +#define GCC_GPU_CFG_AHB_CLK 109 +#define GCC_GPU_GPLL0_CLK_SRC 110 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 111 +#define GCC_GPU_MEMNOC_GFX_CLK 112 +#define GCC_GPU_SMMU_VOTE_CLK 113 +#define GCC_GPU_SNOC_DVM_GFX_CLK 114 +#define GCC_GPU_THROTTLE_CORE_CLK 115 +#define GCC_MMU_TCU_VOTE_CLK 116 +#define GCC_PCIE_AUX_CLK 117 +#define GCC_PCIE_AUX_CLK_SRC 118 +#define GCC_PCIE_AUX_PHY_CLK_SRC 119 +#define GCC_PCIE_CFG_AHB_CLK 120 +#define GCC_PCIE_CLKREF_EN 121 +#define GCC_PCIE_MSTR_AXI_CLK 122 +#define GCC_PCIE_PIPE_CLK 123 +#define GCC_PCIE_PIPE_CLK_SRC 124 +#define GCC_PCIE_RCHNG_PHY_CLK 125 +#define GCC_PCIE_RCHNG_PHY_CLK_SRC 126 +#define GCC_PCIE_SLEEP_CLK 127 +#define GCC_PCIE_SLV_AXI_CLK 128 +#define GCC_PCIE_SLV_Q2A_AXI_CLK 129 +#define GCC_PCIE_TBU_CLK 130 +#define GCC_PCIE_THROTTLE_CORE_CLK 131 +#define GCC_PCIE_THROTTLE_XO_CLK 132 +#define GCC_PCIE_TILE_AXI_SYS_NOC_CLK 133 +#define GCC_PDM2_CLK 134 +#define GCC_PDM2_CLK_SRC 135 +#define GCC_PDM_AHB_CLK 136 +#define GCC_PDM_XO4_CLK 137 +#define GCC_PWM0_XO512_CLK 138 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 139 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 140 +#define GCC_QMIP_DISP_AHB_CLK 141 +#define GCC_QMIP_GPU_CFG_AHB_CLK 142 +#define GCC_QMIP_PCIE_CFG_AHB_CLK 143 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 144 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 145 +#define GCC_QUPV3_WRAP0_CORE_CLK 146 +#define GCC_QUPV3_WRAP0_S0_CLK 147 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 148 +#define GCC_QUPV3_WRAP0_S1_CLK 149 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 150 +#define GCC_QUPV3_WRAP0_S2_CLK 151 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 152 +#define GCC_QUPV3_WRAP0_S3_CLK 153 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 154 +#define GCC_QUPV3_WRAP0_S4_CLK 155 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 156 +#define GCC_QUPV3_WRAP0_S5_CLK 157 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 158 +#define GCC_QUPV3_WRAP0_S6_CLK 159 +#define GCC_QUPV3_WRAP0_S6_CLK_SRC 160 +#define GCC_QUPV3_WRAP0_S7_CLK 161 +#define GCC_QUPV3_WRAP0_S7_CLK_SRC 162 +#define GCC_QUPV3_WRAP0_S8_CLK 163 +#define GCC_QUPV3_WRAP0_S8_CLK_SRC 164 +#define GCC_QUPV3_WRAP0_S9_CLK 165 +#define GCC_QUPV3_WRAP0_S9_CLK_SRC 166 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 167 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 168 +#define GCC_SDCC1_AHB_CLK 169 +#define GCC_SDCC1_APPS_CLK 170 +#define GCC_SDCC1_APPS_CLK_SRC 171 +#define GCC_SDCC1_ICE_CORE_CLK 172 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 173 +#define GCC_SDCC2_AHB_CLK 174 +#define GCC_SDCC2_APPS_CLK 175 +#define GCC_SDCC2_APPS_CLK_SRC 176 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 177 +#define GCC_SYS_NOC_USB2_PRIM_AXI_CLK 178 +#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 179 +#define GCC_TSCSS_AHB_CLK 180 +#define GCC_TSCSS_CLK_SRC 181 +#define GCC_TSCSS_CNTR_CLK 182 +#define GCC_TSCSS_ETU_CLK 183 +#define GCC_UFS_CLKREF_EN 184 +#define GCC_USB20_MASTER_CLK 185 +#define GCC_USB20_MASTER_CLK_SRC 186 +#define GCC_USB20_MOCK_UTMI_CLK 187 +#define GCC_USB20_MOCK_UTMI_CLK_SRC 188 +#define GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC 189 +#define GCC_USB20_SLEEP_CLK 190 +#define GCC_USB30_PRIM_MASTER_CLK 191 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 192 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 193 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 194 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 195 +#define GCC_USB30_PRIM_SLEEP_CLK 196 +#define GCC_USB3_PRIM_CLKREF_EN 197 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 198 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 199 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 200 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 201 +#define GCC_VCODEC0_AXI_CLK 202 +#define GCC_VENUS_AHB_CLK 203 +#define GCC_VENUS_CTL_AXI_CLK 204 +#define GCC_VIDEO_AHB_CLK 205 +#define GCC_VIDEO_AXI0_CLK 206 +#define GCC_VIDEO_THROTTLE_CORE_CLK 207 +#define GCC_VIDEO_VCODEC0_SYS_CLK 208 +#define GCC_VIDEO_VENUS_CLK_SRC 209 +#define GCC_VIDEO_VENUS_CTL_CLK 210 +#define GCC_VIDEO_XO_CLK 211 + +/* GCC power domains */ +#define GCC_CAMSS_TOP_GDSC 0 +#define GCC_EMAC0_GDSC 1 +#define GCC_EMAC1_GDSC 2 +#define GCC_PCIE_GDSC 3 +#define GCC_USB20_GDSC 4 +#define GCC_USB30_PRIM_GDSC 5 +#define GCC_VCODEC0_GDSC 6 +#define GCC_VENUS_GDSC 7 + +/* GCC resets */ +#define GCC_CAMSS_OPE_BCR 0 +#define GCC_CAMSS_TFE_BCR 1 +#define GCC_CAMSS_TOP_BCR 2 +#define GCC_EMAC0_BCR 3 +#define GCC_EMAC1_BCR 4 +#define GCC_GPU_BCR 5 +#define GCC_MMSS_BCR 6 +#define GCC_PCIE_BCR 7 +#define GCC_PCIE_PHY_BCR 8 +#define GCC_PDM_BCR 9 +#define GCC_QUPV3_WRAPPER_0_BCR 10 +#define GCC_QUSB2PHY_PRIM_BCR 11 +#define GCC_SDCC1_BCR 12 +#define GCC_SDCC2_BCR 13 +#define GCC_TSCSS_BCR 14 +#define GCC_USB20_BCR 15 +#define GCC_USB30_PRIM_BCR 16 +#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 17 +#define GCC_USB3_PHY_PRIM_SP0_BCR 18 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 19 +#define GCC_VCODEC0_BCR 20 +#define GCC_VENUS_BCR 21 +#define GCC_VIDEO_INTERFACE_BCR 22 + +#endif From 69df4f26b8d6e506ad49637acf70d6f586159fc1 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 19:20:30 +0530 Subject: [PATCH 0665/1058] clk: qcom: smd-rpm: Add clocks for Shikra Add support for RPM-managed clocks on the Shikra platform. Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-smd-rpm.c | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 103db984a40b9..50daa2b0b8235 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -1289,6 +1289,44 @@ static const struct rpm_smd_clk_desc rpm_clk_qcm2290 = { .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) }; +static struct clk_smd_rpm *shikra_clks[] = { + [RPM_SMD_XO_CLK_SRC] = &clk_smd_rpm_branch_bi_tcxo, + [RPM_SMD_XO_A_CLK_SRC] = &clk_smd_rpm_branch_bi_tcxo_a, + [RPM_SMD_QDSS_CLK] = &clk_smd_rpm_branch_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &clk_smd_rpm_branch_qdss_a_clk, + [RPM_SMD_LN_BB_CLK2] = &clk_smd_rpm_ln_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &clk_smd_rpm_ln_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &clk_smd_rpm_rf_clk1, + [RPM_SMD_RF_CLK1_A]= &clk_smd_rpm_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &clk_smd_rpm_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &clk_smd_rpm_rf_clk2_a, + [RPM_SMD_RF_CLK3] = &clk_smd_rpm_38m4_rf_clk3, + [RPM_SMD_RF_CLK3_A] = &clk_smd_rpm_38m4_rf_clk3_a, + [RPM_SMD_IPA_CLK] = &clk_smd_rpm_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &clk_smd_rpm_ipa_a_clk, + [RPM_SMD_SNOC_PERIPH_CLK] = &clk_smd_rpm_bus_0_snoc_periph_clk, + [RPM_SMD_SNOC_PERIPH_A_CLK] = &clk_smd_rpm_bus_0_snoc_periph_a_clk, + [RPM_SMD_SNOC_LPASS_CLK] = &clk_smd_rpm_bus_5_snoc_lpass_clk, + [RPM_SMD_SNOC_LPASS_A_CLK] = &clk_smd_rpm_bus_5_snoc_lpass_a_clk, + [RPM_SMD_CE1_CLK] = &clk_smd_rpm_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &clk_smd_rpm_ce1_a_clk, + [RPM_SMD_QPIC_CLK] = &clk_smd_rpm_qpic_clk, + [RPM_SMD_QPIC_CLK_A] = &clk_smd_rpm_qpic_a_clk, + [RPM_SMD_HWKM_CLK] = &clk_smd_rpm_hwkm_clk, + [RPM_SMD_HWKM_A_CLK] = &clk_smd_rpm_hwkm_a_clk, + [RPM_SMD_PKA_CLK] = &clk_smd_rpm_pka_clk, + [RPM_SMD_PKA_A_CLK] = &clk_smd_rpm_pka_a_clk, + [RPM_SMD_BIMC_GPU_CLK] = &clk_smd_rpm_bimc_gpu_clk, + [RPM_SMD_BIMC_GPU_A_CLK] = &clk_smd_rpm_bimc_gpu_a_clk, +}; + +static const struct rpm_smd_clk_desc rpm_clk_shikra = { + .clks = shikra_clks, + .num_clks = ARRAY_SIZE(shikra_clks), + .icc_clks = qcm2290_icc_clks, + .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) +}; + static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-mdm9607", .data = &rpm_clk_mdm9607 }, { .compatible = "qcom,rpmcc-msm8226", .data = &rpm_clk_msm8974 }, @@ -1309,6 +1347,7 @@ static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, { .compatible = "qcom,rpmcc-sdm429", .data = &rpm_clk_sdm429 }, { .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 }, + { .compatible = "qcom,rpmcc-shikra", .data = &rpm_clk_shikra }, { .compatible = "qcom,rpmcc-sm6115", .data = &rpm_clk_sm6115 }, { .compatible = "qcom,rpmcc-sm6125", .data = &rpm_clk_sm6125 }, { .compatible = "qcom,rpmcc-sm6375", .data = &rpm_clk_sm6375 }, From 9d6038e23dcde7b57b907c37959ced28b964900f Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 17:37:50 +0530 Subject: [PATCH 0666/1058] clk: qcom: Add support for Global clock controller on Shikra Add support for Global clock controller for Shikra Qualcomm SoC. Signed-off-by: Imran Shaik --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-shikra.c | 4484 +++++++++++++++++++++++++++++++++ 3 files changed, 4494 insertions(+) create mode 100644 drivers/clk/qcom/gcc-shikra.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 7d84c2f1d911a..ddf24fef01ed9 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -155,6 +155,15 @@ config CLK_NORD_GCC SPI, I2C, USB, SD/UFS, PCIe etc. The clock controller is a combination of GCC, SE_GCC, NE_GCC and NW_GCC. +config CLK_SHIKRA_GCC + tristate "Shikra Global Clock Controller" + depends on ARM64 || COMPILE_TEST + select QCOM_GDSC + help + Support for the global clock controller on Shikra devices. + Say Y if you want to use multimedia devices or peripheral + devices such as Camera, Video, UART, SPI, I2C, USB, SD/eMMC etc. + config CLK_X1E80100_CAMCC tristate "X1E80100 Camera Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 58f9a5eb6fd7f..9c01451580d52 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_KAANAPALI_TCSRCC) += tcsrcc-kaanapali.o obj-$(CONFIG_CLK_KAANAPALI_VIDEOCC) += videocc-kaanapali.o obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o +obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_GCC) += gcc-x1e80100.o diff --git a/drivers/clk/qcom/gcc-shikra.c b/drivers/clk/qcom/gcc-shikra.c new file mode 100644 index 0000000000000..3ca5ed7cd48a1 --- /dev/null +++ b/drivers/clk/qcom/gcc-shikra.c @@ -0,0 +1,4484 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "clk-regmap-phy-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_EMAC0_SGMIIPHY_RCLK, + DT_EMAC0_SGMIIPHY_TCLK, + DT_EMAC1_SGMIIPHY_RCLK, + DT_EMAC1_SGMIIPHY_TCLK, + DT_PCIE_PIPE_CLK, + DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +enum { + P_BI_TCXO, + P_EMAC0_SGMIIPHY_RCLK, + P_EMAC0_SGMIIPHY_TCLK, + P_EMAC1_SGMIIPHY_RCLK, + P_EMAC1_SGMIIPHY_TCLK, + P_GPLL0_OUT_AUX2, + P_GPLL0_OUT_EARLY, + P_GPLL10_OUT_MAIN, + P_GPLL11_OUT_AUX, + P_GPLL11_OUT_AUX2, + P_GPLL11_OUT_MAIN, + P_GPLL12_OUT_AUX2, + P_GPLL12_OUT_EARLY, + P_GPLL3_OUT_EARLY, + P_GPLL3_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL5_OUT_MAIN, + P_GPLL6_OUT_EARLY, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_GPLL8_OUT_EARLY, + P_GPLL8_OUT_MAIN, + P_GPLL9_OUT_EARLY, + P_GPLL9_OUT_MAIN, + P_PCIE_PIPE_CLK, + P_SLEEP_CLK, + P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +static const struct pll_vco brammo_vco[] = { + { 500000000, 1250000000, 0 }, +}; + +static const struct pll_vco spark_vco[] = { + { 750000000, 1500000000, 1 }, + { 500000000, 1000000000, 2 }, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll0_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_aux2 = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll0_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_aux2), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll0_out_aux2", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll1 = { + .offset = 0x1000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gpll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +/* 1152.0 MHz Configuration */ +static const struct alpha_pll_config gpll10_config = { + .l = 0x3c, + .alpha = 0x0, + .vco_val = BIT(20), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, +}; + +static struct clk_alpha_pll gpll10 = { + .offset = 0xa000, + .config = &gpll10_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gpll10", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +/* 600.0 MHz Configuration */ +static const struct alpha_pll_config gpll11_config = { + .l = 0x1f, + .alpha = 0x0, + .alpha_hi = 0x40, + .alpha_en_mask = BIT(24), + .vco_val = BIT(21), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, +}; + +static struct clk_alpha_pll gpll11 = { + .offset = 0xb000, + .config = &gpll11_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gpll11", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll12 = { + .offset = 0xc000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gpll12", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll12_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll12_out_aux2 = { + .offset = 0xc000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll12_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_gpll12_out_aux2), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll12_out_aux2", + .parent_hws = (const struct clk_hw*[]) { + &gpll12.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll3 = { + .offset = 0x3000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gpll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll3_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll3_out_main = { + .offset = 0x3000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll3_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll3_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll3_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll3.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gpll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll5 = { + .offset = 0x5000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gpll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6 = { + .offset = 0x6000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gpll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll6_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll6_out_main = { + .offset = 0x6000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll6_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll6_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll6_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll6.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll7 = { + .offset = 0x7000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gpll7", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +/* 533.2 MHz Configuration */ +static const struct alpha_pll_config gpll8_config = { + .l = 0x1b, + .alpha = 0x55555555, + .alpha_hi = 0xc5, + .alpha_en_mask = BIT(24), + .vco_val = BIT(21), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), + .post_div_val = BIT(8), + .post_div_mask = GENMASK(11, 8), + .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, +}; + +static struct clk_alpha_pll gpll8 = { + .offset = 0x8000, + .config = &gpll8_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gpll8", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll8_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll8_out_main = { + .offset = 0x8000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll8_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll8_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll8_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll8.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +/* 1152.0 MHz Configuration */ +static const struct alpha_pll_config gpll9_config = { + .l = 0x3c, + .alpha = 0x0, + .post_div_val = BIT(8), + .post_div_mask = GENMASK(9, 8), + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), + .config_ctl_val = 0x00004289, + .test_ctl_val = 0x08000000, +}; + +static struct clk_alpha_pll gpll9 = { + .offset = 0x9000, + .config = &gpll9_config, + .vco_table = brammo_vco, + .num_vco = ARRAY_SIZE(brammo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gpll9", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll9_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll9_out_main = { + .offset = 0x9000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll9_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll9_out_main), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO_EVO], + .clkr.hw.init = &(const struct clk_init_data){ + .name = "gpll9_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll9.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL6_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll6_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL6_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll6_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL12_OUT_AUX2, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL12_OUT_AUX2, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_13[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_13[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_14[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_15[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL6_OUT_EARLY, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_15[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll6.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_21[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_21[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll7.clkr.hw }, + { .hw = &gpll4.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_22[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL5_OUT_MAIN, 3 }, + { P_GPLL12_OUT_AUX2, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_22[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll5.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_24[] = { + { P_BI_TCXO, 0 }, + { P_GPLL11_OUT_MAIN, 1 }, + { P_GPLL11_OUT_AUX, 2 }, + { P_GPLL11_OUT_AUX2, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_24[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll11.clkr.hw }, + { .hw = &gpll11.clkr.hw }, + { .hw = &gpll11.clkr.hw }, +}; + +static struct clk_regmap_phy_mux gcc_emac0_cc_sgmiiphy_rx_clk_src = { + .reg = 0xad048, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC0_SGMIIPHY_RCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac0_cc_sgmiiphy_tx_clk_src = { + .reg = 0xad040, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC0_SGMIIPHY_TCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac1_cc_sgmiiphy_rx_clk_src = { + .reg = 0xae048, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC1_SGMIIPHY_RCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac1_cc_sgmiiphy_tx_clk_src = { + .reg = 0xae040, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC1_SGMIIPHY_TCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_pipe_clk_src = { + .reg = 0xaf058, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb3_prim_phy_pipe_clk_src = { + .reg = 0x1a05c, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_axi_clk_src = { + .cmd_rcgr = 0x5802c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_axi_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cci_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cci_clk_src = { + .cmd_rcgr = 0x56000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_14, + .freq_tbl = ftbl_gcc_camss_cci_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cci_clk_src", + .parent_data = gcc_parent_data_14, + .num_parents = ARRAY_SIZE(gcc_parent_data_14), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0phytimer_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { + .cmd_rcgr = 0x45000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi0phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { + .cmd_rcgr = 0x4501c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi1phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_mclk0_clk_src[] = { + F(19200000, P_GPLL9_OUT_EARLY, 1, 1, 60), + F(24000000, P_GPLL9_OUT_MAIN, 1, 1, 24), + F(64000000, P_GPLL9_OUT_EARLY, 9, 1, 2), + { } +}; + +static struct clk_rcg2 gcc_camss_mclk0_clk_src = { + .cmd_rcgr = 0x51000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk0_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk1_clk_src = { + .cmd_rcgr = 0x5101c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk1_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk2_clk_src = { + .cmd_rcgr = 0x51038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk2_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk3_clk_src = { + .cmd_rcgr = 0x51054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk3_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ope_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(171428571, P_GPLL0_OUT_EARLY, 3.5, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = { + .cmd_rcgr = 0x55024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_ope_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_ahb_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ope_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_GPLL8_OUT_MAIN, 2, 0, 0), + F(266600000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(465000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(580000000, P_GPLL8_OUT_EARLY, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ope_clk_src = { + .cmd_rcgr = 0x55004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_ope_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(128000000, P_GPLL10_OUT_MAIN, 9, 0, 0), + F(135529412, P_GPLL10_OUT_MAIN, 8.5, 0, 0), + F(144000000, P_GPLL10_OUT_MAIN, 8, 0, 0), + F(153600000, P_GPLL10_OUT_MAIN, 7.5, 0, 0), + F(164571429, P_GPLL10_OUT_MAIN, 7, 0, 0), + F(177230769, P_GPLL10_OUT_MAIN, 6.5, 0, 0), + F(192000000, P_GPLL10_OUT_MAIN, 6, 0, 0), + F(209454545, P_GPLL10_OUT_MAIN, 5.5, 0, 0), + F(230400000, P_GPLL10_OUT_MAIN, 5, 0, 0), + F(256000000, P_GPLL10_OUT_MAIN, 4.5, 0, 0), + F(288000000, P_GPLL10_OUT_MAIN, 4, 0, 0), + F(329142857, P_GPLL10_OUT_MAIN, 3.5, 0, 0), + F(384000000, P_GPLL10_OUT_MAIN, 3, 0, 0), + F(460800000, P_GPLL10_OUT_MAIN, 2.5, 0, 0), + F(576000000, P_GPLL10_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_0_clk_src = { + .cmd_rcgr = 0x52004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_0_csid_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(120000000, P_GPLL0_OUT_EARLY, 5, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + F(426400000, P_GPLL3_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = { + .cmd_rcgr = 0x52094, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_csid_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_tfe_1_clk_src = { + .cmd_rcgr = 0x52024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = { + .cmd_rcgr = 0x520b4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_csid_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_cphy_rx_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + F(341333333, P_GPLL6_OUT_EARLY, 1, 4, 9), + F(384000000, P_GPLL6_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = { + .cmd_rcgr = 0x52064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_15, + .freq_tbl = ftbl_gcc_camss_tfe_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_cphy_rx_clk_src", + .parent_data = gcc_parent_data_15, + .num_parents = ARRAY_SIZE(gcc_parent_data_15), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_top_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0), + F(80000000, P_GPLL0_OUT_EARLY, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_top_ahb_clk_src = { + .cmd_rcgr = 0x58010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_top_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_top_ahb_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_axi_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_axi_clk_src = { + .cmd_rcgr = 0x109dc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = { + .cmd_rcgr = 0xad01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = { + F(250000000, P_GPLL12_OUT_AUX2, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_ptp_clk_src = { + .cmd_rcgr = 0xad064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = { + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(125000000, P_GPLL12_OUT_AUX2, 4, 0, 0), + F(250000000, P_GPLL12_OUT_EARLY, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_rgmii_clk_src = { + .cmd_rcgr = 0xad04c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_axi_clk_src = { + .cmd_rcgr = 0x109fc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_phy_aux_clk_src = { + .cmd_rcgr = 0xae01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_ptp_clk_src = { + .cmd_rcgr = 0xae064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { + .cmd_rcgr = 0xae04c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x4d004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x4e004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x4f004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_clk_src = { + .cmd_rcgr = 0xaf074, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = { + .cmd_rcgr = 0xaf05c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_phy_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_rchng_phy_clk_src[] = { + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = { + .cmd_rcgr = 0xaf028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_rchng_phy_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_AUX2, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x20010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75), + F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25), + F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15), + F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375), + F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75), + F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x1f148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x1f278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x1f3a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x1f4d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x1f608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x1f738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { + .name = "gcc_qupv3_wrap0_s6_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { + .cmd_rcgr = 0x1f868, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { + .name = "gcc_qupv3_wrap0_s7_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { + .cmd_rcgr = 0x1f998, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s8_clk_src_init = { + .name = "gcc_qupv3_wrap0_s8_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s8_clk_src = { + .cmd_rcgr = 0x1fac8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s8_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s9_clk_src_init = { + .name = "gcc_qupv3_wrap0_s9_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s9_clk_src = { + .cmd_rcgr = 0x1fbf8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s9_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3), + F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x38028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x38010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1e00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_21, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_21, + .num_parents = ARRAY_SIZE(gcc_parent_data_21), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static struct clk_rcg2 gcc_tscss_clk_src = { + .cmd_rcgr = 0xac004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_22, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_clk_src", + .parent_data = gcc_parent_data_22, + .num_parents = ARRAY_SIZE(gcc_parent_data_22), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb20_master_clk_src[] = { + F(60000000, P_GPLL0_OUT_AUX2, 5, 0, 0), + F(120000000, P_GPLL0_OUT_EARLY, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb20_master_clk_src = { + .cmd_rcgr = 0xb003c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb20_master_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb20_mock_utmi_clk_src = { + .cmd_rcgr = 0xb0020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_13, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_clk_src", + .parent_data = gcc_parent_data_13, + .num_parents = ARRAY_SIZE(gcc_parent_data_13), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0x1a01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0x1a034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0x1a060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_video_venus_clk_src[] = { + F(133333333, P_GPLL11_OUT_MAIN, 4.5, 0, 0), + F(240000000, P_GPLL11_OUT_MAIN, 2.5, 0, 0), + F(300000000, P_GPLL11_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL11_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_video_venus_clk_src = { + .cmd_rcgr = 0x6d000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_24, + .freq_tbl = ftbl_gcc_video_venus_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_clk_src", + .parent_data = gcc_parent_data_24, + .num_parents = ARRAY_SIZE(gcc_parent_data_24), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gcc_usb20_mock_utmi_postdiv_clk_src = { + .reg = 0xb0038, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = { + .reg = 0x1a04c, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_ahb2phy_csi_clk = { + .halt_reg = 0x1d004, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x1d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy_csi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_usb_clk = { + .halt_reg = 0x1d008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy_usb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x23004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x23004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cam_throttle_nrt_clk = { + .halt_reg = 0x17070, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17070, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cam_throttle_nrt_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cam_throttle_rt_clk = { + .halt_reg = 0x1706c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1706c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cam_throttle_rt_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_axi_clk = { + .halt_reg = 0x58044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_atb_clk = { + .halt_reg = 0x5804c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x5804c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_atb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_dragonlink_atb_clk = { + .halt_reg = 0x58060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x58060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x58060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_dragonlink_atb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_nts_xo_clk = { + .halt_reg = 0x58050, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x58050, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x58050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_nts_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_0_clk = { + .halt_reg = 0x56018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x56018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_cci_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_0_clk = { + .halt_reg = 0x52088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cphy_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_1_clk = { + .halt_reg = 0x5208c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5208c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cphy_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0phytimer_clk = { + .halt_reg = 0x45018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1phytimer_clk = { + .halt_reg = 0x45034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk0_clk = { + .halt_reg = 0x51018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk1_clk = { + .halt_reg = 0x51034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk2_clk = { + .halt_reg = 0x51050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk3_clk = { + .halt_reg = 0x5106c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5106c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_nrt_axi_clk = { + .halt_reg = 0x58054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ope_ahb_clk = { + .halt_reg = 0x5503c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5503c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_ope_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ope_clk = { + .halt_reg = 0x5501c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5501c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_ope_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_rt_axi_clk = { + .halt_reg = 0x5805c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5805c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_clk = { + .halt_reg = 0x5201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5201c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_cphy_rx_clk = { + .halt_reg = 0x5207c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5207c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_csid_clk = { + .halt_reg = 0x520ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x520ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_0_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_clk = { + .halt_reg = 0x5203c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5203c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_cphy_rx_clk = { + .halt_reg = 0x52080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_csid_clk = { + .halt_reg = 0x520cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x520cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_1_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_top_ahb_clk = { + .halt_reg = 0x58028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_top_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb2_prim_axi_clk = { + .halt_reg = 0x111c4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x111c4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x111c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb2_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a07c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1a07c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a07c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x71000, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x71000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_memnoc_pcie_sf_clk = { + .halt_reg = 0x29044, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x29044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x29044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_memnoc_pcie_sf_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap_div gcc_disp_gpll0_clk_src = { + .reg = 0x17058, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gcc_disp_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_disp_gpll0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x17020, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_core_clk = { + .halt_reg = 0x17064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ahb_clk = { + .halt_reg = 0xad010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xad010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_clk = { + .halt_reg = 0xad014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xad014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_sys_noc_clk = { + .halt_reg = 0x109d4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x109d4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x109d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_rx_clk = { + .halt_reg = 0xad044, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xad044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_tx_clk = { + .halt_reg = 0xad03c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xad03c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad03c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_phy_aux_clk = { + .halt_reg = 0xad018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ptp_clk = { + .halt_reg = 0xad034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rgmii_clk = { + .halt_reg = 0xad038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ahb_clk = { + .halt_reg = 0xae010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xae010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_clk = { + .halt_reg = 0xae014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xae014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_sys_noc_clk = { + .halt_reg = 0x109f4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x109f4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x109f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_rx_clk = { + .halt_reg = 0xae044, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xae044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_tx_clk = { + .halt_reg = 0xae03c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xae03c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae03c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_phy_aux_clk = { + .halt_reg = 0xae018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ptp_clk = { + .halt_reg = 0xae034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rgmii_clk = { + .halt_reg = 0xae038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x4d000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x4e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4e000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x4f000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0_out_aux2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x3600c, + .halt_check = BRANCH_VOTED, + .hwcg_reg = 0x3600c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_smmu_vote_clk = { + .halt_reg = 0x7d000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_smmu_vote_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x36018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_core_clk = { + .halt_reg = 0x36048, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36048, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mmu_tcu_vote_clk = { + .halt_reg = 0x7d06c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d06c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_mmu_tcu_vote_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_aux_clk = { + .halt_reg = 0xaf044, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_cfg_ahb_clk = { + .halt_reg = 0xaf010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_clkref_en = { + .halt_reg = 0xb8000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xb8000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_mstr_axi_clk = { + .halt_reg = 0xaf020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_pipe_clk = { + .halt_reg = 0xaf050, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xaf050, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rchng_phy_clk = { + .halt_reg = 0xaf040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_rchng_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_sleep_clk = { + .halt_reg = 0xaf04c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf04c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_sleep_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_axi_clk = { + .halt_reg = 0xaf018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_q2a_axi_clk = { + .halt_reg = 0xaf014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_tbu_clk = { + .halt_reg = 0xaf098, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf098, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_throttle_core_clk = { + .halt_reg = 0xaf094, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf094, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_throttle_xo_clk = { + .halt_reg = 0xaf090, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_throttle_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_tile_axi_sys_noc_clk = { + .halt_reg = 0x10f2c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10f2c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10f2c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_tile_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x2000c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2000c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x20004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x20004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x20004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x20008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pwm0_xo512_clk = { + .halt_reg = 0x2002c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2002c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pwm0_xo512_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0x17060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0x17018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_gpu_cfg_ahb_clk = { + .halt_reg = 0x36040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_gpu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_pcie_cfg_ahb_clk = { + .halt_reg = 0xaf08c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf08c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x17010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x1f014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1f00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x1f144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x1f274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x1f3a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x1f4d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x1f604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x1f734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s6_clk = { + .halt_reg = 0x1f864, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s6_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s7_clk = { + .halt_reg = 0x1f994, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s7_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s8_clk = { + .halt_reg = 0x1fac4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s8_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s8_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s9_clk = { + .halt_reg = 0x1fbf4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s9_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s9_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x1f004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x1f008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x38008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x38008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x38008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x3800c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x3800c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3800c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ice_core_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc1_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1e008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb2_prim_axi_clk = { + .halt_reg = 0x10a14, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10a14, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10a14, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sys_noc_usb2_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a078, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1a078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a078, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sys_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_ahb_clk = { + .halt_reg = 0xac024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xac024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xac024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_cntr_clk = { + .halt_reg = 0xac020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xac020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_cntr_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_tscss_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_etu_clk = { + .halt_reg = 0xac01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xac01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_etu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_tscss_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_clkref_en = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_master_clk = { + .halt_reg = 0xb0010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb0010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb0010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_master_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_mock_utmi_clk = { + .halt_reg = 0xb001c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sleep_clk = { + .halt_reg = 0xb0018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb0018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0x1a010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1a010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0x1a018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0x1a014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_en = { + .halt_reg = 0x9f000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0x1a054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_reg = 0x1a058, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x1a058, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vcodec0_axi_clk = { + .halt_reg = 0x6e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_vcodec0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_venus_ahb_clk = { + .halt_reg = 0x6e010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_venus_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_venus_ctl_axi_clk = { + .halt_reg = 0x6e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_venus_ctl_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0x1701c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1701c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1701c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_core_clk = { + .halt_reg = 0x17068, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17068, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_vcodec0_sys_clk = { + .halt_reg = 0x6d044, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x6d044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6d044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_vcodec0_sys_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_venus_ctl_clk = { + .halt_reg = 0x6d02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6d02c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_ctl_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gcc_camss_top_gdsc = { + .gdscr = 0x58004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_camss_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_emac0_gdsc = { + .gdscr = 0xad004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_emac0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_emac1_gdsc = { + .gdscr = 0xae004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_emac1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_gdsc = { + .gdscr = 0xaf004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb20_gdsc = { + .gdscr = 0xb0004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_usb20_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb30_prim_gdsc = { + .gdscr = 0x1a004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_venus_gdsc = { + .gdscr = 0x6d01c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_venus_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_vcodec0_gdsc = { + .gdscr = 0x6d038, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_vcodec0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &gcc_venus_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gcc_shikra_clocks[] = { + [GCC_AHB2PHY_CSI_CLK] = &gcc_ahb2phy_csi_clk.clkr, + [GCC_AHB2PHY_USB_CLK] = &gcc_ahb2phy_usb_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAM_THROTTLE_NRT_CLK] = &gcc_cam_throttle_nrt_clk.clkr, + [GCC_CAM_THROTTLE_RT_CLK] = &gcc_cam_throttle_rt_clk.clkr, + [GCC_CAMSS_AXI_CLK] = &gcc_camss_axi_clk.clkr, + [GCC_CAMSS_AXI_CLK_SRC] = &gcc_camss_axi_clk_src.clkr, + [GCC_CAMSS_CAMNOC_ATB_CLK] = &gcc_camss_camnoc_atb_clk.clkr, + [GCC_CAMSS_CAMNOC_DRAGONLINK_ATB_CLK] = &gcc_camss_camnoc_dragonlink_atb_clk.clkr, + [GCC_CAMSS_CAMNOC_NTS_XO_CLK] = &gcc_camss_camnoc_nts_xo_clk.clkr, + [GCC_CAMSS_CCI_0_CLK] = &gcc_camss_cci_0_clk.clkr, + [GCC_CAMSS_CCI_CLK_SRC] = &gcc_camss_cci_clk_src.clkr, + [GCC_CAMSS_CPHY_0_CLK] = &gcc_camss_cphy_0_clk.clkr, + [GCC_CAMSS_CPHY_1_CLK] = &gcc_camss_cphy_1_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK_SRC] = &gcc_camss_csi0phytimer_clk_src.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK_SRC] = &gcc_camss_csi1phytimer_clk_src.clkr, + [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr, + [GCC_CAMSS_MCLK0_CLK_SRC] = &gcc_camss_mclk0_clk_src.clkr, + [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr, + [GCC_CAMSS_MCLK1_CLK_SRC] = &gcc_camss_mclk1_clk_src.clkr, + [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr, + [GCC_CAMSS_MCLK2_CLK_SRC] = &gcc_camss_mclk2_clk_src.clkr, + [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr, + [GCC_CAMSS_MCLK3_CLK_SRC] = &gcc_camss_mclk3_clk_src.clkr, + [GCC_CAMSS_NRT_AXI_CLK] = &gcc_camss_nrt_axi_clk.clkr, + [GCC_CAMSS_OPE_AHB_CLK] = &gcc_camss_ope_ahb_clk.clkr, + [GCC_CAMSS_OPE_AHB_CLK_SRC] = &gcc_camss_ope_ahb_clk_src.clkr, + [GCC_CAMSS_OPE_CLK] = &gcc_camss_ope_clk.clkr, + [GCC_CAMSS_OPE_CLK_SRC] = &gcc_camss_ope_clk_src.clkr, + [GCC_CAMSS_RT_AXI_CLK] = &gcc_camss_rt_axi_clk.clkr, + [GCC_CAMSS_TFE_0_CLK] = &gcc_camss_tfe_0_clk.clkr, + [GCC_CAMSS_TFE_0_CLK_SRC] = &gcc_camss_tfe_0_clk_src.clkr, + [GCC_CAMSS_TFE_0_CPHY_RX_CLK] = &gcc_camss_tfe_0_cphy_rx_clk.clkr, + [GCC_CAMSS_TFE_0_CSID_CLK] = &gcc_camss_tfe_0_csid_clk.clkr, + [GCC_CAMSS_TFE_0_CSID_CLK_SRC] = &gcc_camss_tfe_0_csid_clk_src.clkr, + [GCC_CAMSS_TFE_1_CLK] = &gcc_camss_tfe_1_clk.clkr, + [GCC_CAMSS_TFE_1_CLK_SRC] = &gcc_camss_tfe_1_clk_src.clkr, + [GCC_CAMSS_TFE_1_CPHY_RX_CLK] = &gcc_camss_tfe_1_cphy_rx_clk.clkr, + [GCC_CAMSS_TFE_1_CSID_CLK] = &gcc_camss_tfe_1_csid_clk.clkr, + [GCC_CAMSS_TFE_1_CSID_CLK_SRC] = &gcc_camss_tfe_1_csid_clk_src.clkr, + [GCC_CAMSS_TFE_CPHY_RX_CLK_SRC] = &gcc_camss_tfe_cphy_rx_clk_src.clkr, + [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, + [GCC_CAMSS_TOP_AHB_CLK_SRC] = &gcc_camss_top_ahb_clk_src.clkr, + [GCC_CFG_NOC_USB2_PRIM_AXI_CLK] = &gcc_cfg_noc_usb2_prim_axi_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DDRSS_MEMNOC_PCIE_SF_CLK] = &gcc_ddrss_memnoc_pcie_sf_clk.clkr, + [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, + [GCC_EMAC0_AHB_CLK] = &gcc_emac0_ahb_clk.clkr, + [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr, + [GCC_EMAC0_AXI_CLK_SRC] = &gcc_emac0_axi_clk_src.clkr, + [GCC_EMAC0_AXI_SYS_NOC_CLK] = &gcc_emac0_axi_sys_noc_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK] = &gcc_emac0_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK] = &gcc_emac0_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC0_PHY_AUX_CLK] = &gcc_emac0_phy_aux_clk.clkr, + [GCC_EMAC0_PHY_AUX_CLK_SRC] = &gcc_emac0_phy_aux_clk_src.clkr, + [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr, + [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr, + [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr, + [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr, + [GCC_EMAC1_AHB_CLK] = &gcc_emac1_ahb_clk.clkr, + [GCC_EMAC1_AXI_CLK] = &gcc_emac1_axi_clk.clkr, + [GCC_EMAC1_AXI_CLK_SRC] = &gcc_emac1_axi_clk_src.clkr, + [GCC_EMAC1_AXI_SYS_NOC_CLK] = &gcc_emac1_axi_sys_noc_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK] = &gcc_emac1_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK] = &gcc_emac1_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC1_PHY_AUX_CLK] = &gcc_emac1_phy_aux_clk.clkr, + [GCC_EMAC1_PHY_AUX_CLK_SRC] = &gcc_emac1_phy_aux_clk_src.clkr, + [GCC_EMAC1_PTP_CLK] = &gcc_emac1_ptp_clk.clkr, + [GCC_EMAC1_PTP_CLK_SRC] = &gcc_emac1_ptp_clk_src.clkr, + [GCC_EMAC1_RGMII_CLK] = &gcc_emac1_rgmii_clk.clkr, + [GCC_EMAC1_RGMII_CLK_SRC] = &gcc_emac1_rgmii_clk_src.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SMMU_VOTE_CLK] = &gcc_gpu_smmu_vote_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, + [GCC_MMU_TCU_VOTE_CLK] = &gcc_mmu_tcu_vote_clk.clkr, + [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr, + [GCC_PCIE_AUX_CLK_SRC] = &gcc_pcie_aux_clk_src.clkr, + [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr, + [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr, + [GCC_PCIE_CLKREF_EN] = &gcc_pcie_clkref_en.clkr, + [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr, + [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr, + [GCC_PCIE_PIPE_CLK_SRC] = &gcc_pcie_pipe_clk_src.clkr, + [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr, + [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr, + [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr, + [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr, + [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr, + [GCC_PCIE_TBU_CLK] = &gcc_pcie_tbu_clk.clkr, + [GCC_PCIE_THROTTLE_CORE_CLK] = &gcc_pcie_throttle_core_clk.clkr, + [GCC_PCIE_THROTTLE_XO_CLK] = &gcc_pcie_throttle_xo_clk.clkr, + [GCC_PCIE_TILE_AXI_SYS_NOC_CLK] = &gcc_pcie_tile_axi_sys_noc_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PWM0_XO512_CLK] = &gcc_pwm0_xo512_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_GPU_CFG_AHB_CLK] = &gcc_qmip_gpu_cfg_ahb_clk.clkr, + [GCC_QMIP_PCIE_CFG_AHB_CLK] = &gcc_qmip_pcie_cfg_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr, + [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr, + [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr, + [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr, + [GCC_QUPV3_WRAP0_S8_CLK] = &gcc_qupv3_wrap0_s8_clk.clkr, + [GCC_QUPV3_WRAP0_S8_CLK_SRC] = &gcc_qupv3_wrap0_s8_clk_src.clkr, + [GCC_QUPV3_WRAP0_S9_CLK] = &gcc_qupv3_wrap0_s9_clk.clkr, + [GCC_QUPV3_WRAP0_S9_CLK_SRC] = &gcc_qupv3_wrap0_s9_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_USB2_PRIM_AXI_CLK] = &gcc_sys_noc_usb2_prim_axi_clk.clkr, + [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, + [GCC_TSCSS_AHB_CLK] = &gcc_tscss_ahb_clk.clkr, + [GCC_TSCSS_CLK_SRC] = &gcc_tscss_clk_src.clkr, + [GCC_TSCSS_CNTR_CLK] = &gcc_tscss_cntr_clk.clkr, + [GCC_TSCSS_ETU_CLK] = &gcc_tscss_etu_clk.clkr, + [GCC_UFS_CLKREF_EN] = &gcc_ufs_clkref_en.clkr, + [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr, + [GCC_USB20_MASTER_CLK_SRC] = &gcc_usb20_master_clk_src.clkr, + [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr, + [GCC_USB20_MOCK_UTMI_CLK_SRC] = &gcc_usb20_mock_utmi_clk_src.clkr, + [GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb20_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_CLKREF_EN] = &gcc_usb3_prim_clkref_en.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr, + [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr, + [GCC_VENUS_AHB_CLK] = &gcc_venus_ahb_clk.clkr, + [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, + [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr, + [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr, + [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr, + [GPLL1] = &gpll1.clkr, + [GPLL10] = &gpll10.clkr, + [GPLL11] = &gpll11.clkr, + [GPLL12] = &gpll12.clkr, + [GPLL12_OUT_AUX2] = &gpll12_out_aux2.clkr, + [GPLL3] = &gpll3.clkr, + [GPLL3_OUT_MAIN] = &gpll3_out_main.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL5] = &gpll5.clkr, + [GPLL6] = &gpll6.clkr, + [GPLL6_OUT_MAIN] = &gpll6_out_main.clkr, + [GPLL7] = &gpll7.clkr, + [GPLL8] = &gpll8.clkr, + [GPLL8_OUT_MAIN] = &gpll8_out_main.clkr, + [GPLL9] = &gpll9.clkr, + [GPLL9_OUT_MAIN] = &gpll9_out_main.clkr, +}; + +static struct gdsc *gcc_shikra_gdscs[] = { + [GCC_CAMSS_TOP_GDSC] = &gcc_camss_top_gdsc, + [GCC_EMAC0_GDSC] = &gcc_emac0_gdsc, + [GCC_EMAC1_GDSC] = &gcc_emac1_gdsc, + [GCC_PCIE_GDSC] = &gcc_pcie_gdsc, + [GCC_USB20_GDSC] = &gcc_usb20_gdsc, + [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc, + [GCC_VCODEC0_GDSC] = &gcc_vcodec0_gdsc, + [GCC_VENUS_GDSC] = &gcc_venus_gdsc, +}; + +static const struct qcom_reset_map gcc_shikra_resets[] = { + [GCC_CAMSS_OPE_BCR] = { 0x55000 }, + [GCC_CAMSS_TFE_BCR] = { 0x52000 }, + [GCC_CAMSS_TOP_BCR] = { 0x58000 }, + [GCC_EMAC0_BCR] = { 0xad000 }, + [GCC_EMAC1_BCR] = { 0xae000 }, + [GCC_GPU_BCR] = { 0x36000 }, + [GCC_MMSS_BCR] = { 0x17000 }, + [GCC_PCIE_BCR] = { 0xaf000 }, + [GCC_PCIE_PHY_BCR] = { 0xb1000 }, + [GCC_PDM_BCR] = { 0x20000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x1f000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_SDCC1_BCR] = { 0x38000 }, + [GCC_SDCC2_BCR] = { 0x1e000 }, + [GCC_TSCSS_BCR] = { 0xac000 }, + [GCC_USB20_BCR] = { 0xb0000 }, + [GCC_USB30_PRIM_BCR] = { 0x1a000 }, + [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x1b008 }, + [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x1b000 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x1d000 }, + [GCC_VCODEC0_BCR] = { 0x6d034 }, + [GCC_VENUS_BCR] = { 0x6d018 }, + [GCC_VIDEO_INTERFACE_BCR] = { 0x6e000 }, +}; + +static struct clk_alpha_pll *gcc_shikra_plls[] = { + &gpll10, + &gpll11, + &gpll8, + &gpll9, +}; + +static u32 gcc_shikra_critical_cbcrs[] = { + 0x17008, /* GCC_CAMERA_AHB_CLK */ + 0x17028, /* GCC_CAMERA_XO_CLK */ + 0x1700c, /* GCC_DISP_AHB_CLK */ + 0x1702c, /* GCC_DISP_XO_CLK */ + 0x36004, /* GCC_GPU_CFG_AHB_CLK */ + 0x36100, /* GCC_GPU_IREF_CLK */ + 0x79004, /* GCC_SYS_NOC_CPUSS_AHB_CLK */ + 0x17004, /* GCC_VIDEO_AHB_CLK */ + 0x17024, /* GCC_VIDEO_XO_CLK */ +}; + +static const struct clk_rcg_dfs_data gcc_shikra_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s8_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s9_clk_src), +}; + +static const struct regmap_config gcc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc7000, + .fast_io = true, +}; + +static struct qcom_cc_driver_data gcc_shikra_driver_data = { + .alpha_plls = gcc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(gcc_shikra_plls), + .clk_cbcrs = gcc_shikra_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gcc_shikra_critical_cbcrs), + .dfs_rcgs = gcc_shikra_dfs_clocks, + .num_dfs_rcgs = ARRAY_SIZE(gcc_shikra_dfs_clocks), +}; + +static const struct qcom_cc_desc gcc_shikra_desc = { + .config = &gcc_shikra_regmap_config, + .clks = gcc_shikra_clocks, + .num_clks = ARRAY_SIZE(gcc_shikra_clocks), + .resets = gcc_shikra_resets, + .num_resets = ARRAY_SIZE(gcc_shikra_resets), + .gdscs = gcc_shikra_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_shikra_gdscs), + .driver_data = &gcc_shikra_driver_data, +}; + +static const struct of_device_id gcc_shikra_match_table[] = { + { .compatible = "qcom,shikra-gcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_shikra_match_table); + +static int gcc_shikra_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &gcc_shikra_desc); +} + +static struct platform_driver gcc_shikra_driver = { + .probe = gcc_shikra_probe, + .driver = { + .name = "gcc-shikra", + .of_match_table = gcc_shikra_match_table, + }, +}; + +static int __init gcc_shikra_init(void) +{ + return platform_driver_register(&gcc_shikra_driver); +} +subsys_initcall(gcc_shikra_init); + +static void __exit gcc_shikra_exit(void) +{ + platform_driver_unregister(&gcc_shikra_driver); +} +module_exit(gcc_shikra_exit); + +MODULE_DESCRIPTION("QTI GCC SHIKRA Driver"); +MODULE_LICENSE("GPL"); From 83581fdee1d510226d804c2f84dd301265bcff73 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 18:16:03 +0530 Subject: [PATCH 0667/1058] arm64: defconfig: Enable GCC on Shikra EVK boards Enable the GCC driver on the Qualcomm Shikra EVK boards. Signed-off-by: Imran Shaik --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc5..c874b9d4aab31 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1446,6 +1446,7 @@ CONFIG_CLK_IMX8QXP=y CONFIG_CLK_IMX8ULP=y CONFIG_CLK_IMX93=y CONFIG_CLK_IMX95_BLK_CTL=y +CONFIG_CLK_SHIKRA_GCC=y CONFIG_TI_SCI_CLK=y CONFIG_COMMON_CLK_MT8192_AUDSYS=y CONFIG_COMMON_CLK_MT8192_CAMSYS=y From e27c2d660d1b79bf5627d3dd8ccd080ef84d54df Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 21 Mar 2026 22:42:58 +0530 Subject: [PATCH 0668/1058] dt-bindings: phy: qcom,msm8998-qmp-usb3-phy: Add support for Shikra Update dt-bindings to add Shikra to QMP Phy list. Signed-off-by: Krishna Kurapati --- .../devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml index 1636285fbe535..8402fe4a96e03 100644 --- a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml @@ -20,6 +20,7 @@ properties: - qcom,qcm2290-qmp-usb3-phy - qcom,qcs615-qmp-usb3-phy - qcom,sdm660-qmp-usb3-phy + - qcom,shikra-qmp-usb3-phy - qcom,sm6115-qmp-usb3-phy reg: @@ -116,6 +117,7 @@ allOf: contains: enum: - qcom,qcm2290-qmp-usb3-phy + - qcom,shikra-qmp-usb3-phy - qcom,sm6115-qmp-usb3-phy then: properties: From 2aca08002aad0d81ffb2cafcf7890bf4f2c4c356 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 21 Mar 2026 22:43:45 +0530 Subject: [PATCH 0669/1058] dt-bindings: phy: qcom,qusb2: Add bindings for Shikra Update dt-bindings to add Shikra to QUSB2 Phy list. Signed-off-by: Krishna Kurapati --- Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml index 449c2a7e5fecf..001fd0ccc9852 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml @@ -28,6 +28,7 @@ properties: - qcom,qcm2290-qusb2-phy - qcom,qcs615-qusb2-phy - qcom,sdm660-qusb2-phy + - qcom,shikra-qusb2-phy - qcom,sm4250-qusb2-phy - qcom,sm6115-qusb2-phy - items: From 980d6415bb6e276ee4ad9a3e4e52b3174e7fc8e9 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 21 Mar 2026 22:45:05 +0530 Subject: [PATCH 0670/1058] dt-bindings: usb: qcom,snps-dwc3: Add Shikra compatible Introduce the compatible definition for Shikra QCOM SNPS DWC3. Signed-off-by: Krishna Kurapati --- Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml index 8201656b41ed7..d5368b423a9ac 100644 --- a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml @@ -60,6 +60,7 @@ properties: - qcom,sdx55-dwc3 - qcom,sdx65-dwc3 - qcom,sdx75-dwc3 + - qcom,shikra-dwc3 - qcom,sm4250-dwc3 - qcom,sm6115-dwc3 - qcom,sm6125-dwc3 @@ -358,6 +359,7 @@ allOf: - qcom,sar2130p-dwc3 - qcom,sc8180x-dwc3 - qcom,sc8180x-dwc3-mp + - qcom,shikra-dwc3 - qcom,sm4250-dwc3 - qcom,sm6115-dwc3 - qcom,sm6125-dwc3 @@ -434,6 +436,7 @@ allOf: - qcom,ipq8074-dwc3 - qcom,msm8953-dwc3 - qcom,msm8998-dwc3 + - qcom,shikra-dwc3 then: properties: interrupts: From 4c42cf1434b794958938fabab2917fe2735a69a9 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 21 Mar 2026 22:47:32 +0530 Subject: [PATCH 0671/1058] phy: qcom-qusb2: Add support for Shikra Add init sequence and phy configuration for Shikra. Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index eb93015be841f..8014141e92f2a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -381,6 +381,19 @@ static const struct qusb2_phy_cfg sdm660_phy_cfg = { .autoresume_en = BIT(3), }; +static const struct qusb2_phy_cfg shikra_phy_cfg = { + .tbl = qcs615_init_tbl, + .tbl_num = ARRAY_SIZE(qcs615_init_tbl), + .regs = ipq6018_regs_layout, + + .has_pll_test = true, + .se_clk_scheme_default = true, + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), + .mask_core_ready = PLL_LOCKED, + .autoresume_en = BIT(3), + .update_tune1_with_efuse = false, +}; + static const struct qusb2_phy_cfg sm6115_phy_cfg = { .tbl = sm6115_init_tbl, .tbl_num = ARRAY_SIZE(sm6115_init_tbl), @@ -958,6 +971,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { }, { .compatible = "qcom,sdm660-qusb2-phy", .data = &sdm660_phy_cfg, + }, { + .compatible = "qcom,shikra-qusb2-phy", + .data = &shikra_phy_cfg, }, { .compatible = "qcom,sm4250-qusb2-phy", .data = &sm6115_phy_cfg, From 176857bedf43d2163cff4d4730cc6b8805fff939 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 21 Mar 2026 22:48:49 +0530 Subject: [PATCH 0672/1058] phy: qcom: qmp-usbc: Add qmp configuration for Shikra Provide PHY configuration for the USB QMP PHY for Shikra Platform. Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-qmp-usbc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c index ab3055bb5b0c1..fc727e6ae1134 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c @@ -2019,6 +2019,9 @@ static const struct of_device_id qmp_usbc_of_match_table[] = { }, { .compatible = "qcom,sdm660-qmp-usb3-phy", .data = &sdm660_usb3phy_cfg, + }, { + .compatible = "qcom,shikra-qmp-usb3-phy", + .data = &qcs615_usb3phy_cfg, }, { .compatible = "qcom,sm6115-qmp-usb3-phy", .data = &qcm2290_usb3phy_cfg, From b97aaa730afa08f3f96c0285f999beee82fb804f Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 1 Apr 2026 11:52:10 +0530 Subject: [PATCH 0673/1058] arm64: defconfig: Enable interconnect driver for Shikra Enable the shikra interconnect driver so that consumers are able to obtain their path handles properly. Signed-off-by: Raviteja Laggyshetty --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c874b9d4aab31..ac82018addff9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1879,6 +1879,7 @@ CONFIG_INTERCONNECT_QCOM_SC8180X=y CONFIG_INTERCONNECT_QCOM_SC8280XP=y CONFIG_INTERCONNECT_QCOM_SDM845=y CONFIG_INTERCONNECT_QCOM_SDX75=y +CONFIG_INTERCONNECT_QCOM_SHIKRA=y CONFIG_INTERCONNECT_QCOM_SM6115=y CONFIG_INTERCONNECT_QCOM_SM6350=y CONFIG_INTERCONNECT_QCOM_MILOS=y From 1abb5d71505df2c09272f8e999bb6fcb7e116c25 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 7 Apr 2026 11:00:02 +0530 Subject: [PATCH 0674/1058] dt-bindings: mfd: qcom,tcsr: Add compatible for Shikra Document the qcom,shikra-tcsr compatible. Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 7dd2fe035e6d3..fba5ff5283b15 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -34,6 +34,7 @@ properties: - qcom,sdx55-tcsr - qcom,sdx65-tcsr - qcom,sdx75-tcsr + - qcom,shikra-tcsr - qcom,sm4450-tcsr - qcom,sm6115-tcsr - qcom,sm8150-tcsr From 115a6eba4adb5da3fa341f5d6f6673130bf2eac2 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 10 Apr 2026 10:20:03 +0530 Subject: [PATCH 0675/1058] dt-bindings: cpufreq: qcom-hw: Document Shikra CPUFREQ Hardware The Qualcomm Shikra SoCs use RIMPS (RISC V based Integrated Manager for Power States) hardware for cpufreq scaling, which is functionally similar to EPSS, but supports only up to 12 frequency lookup table (LUT) entries. Signed-off-by: Imran Shaik --- .../devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml index 98eb36bff1727..fa54fb7ef5246 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml @@ -54,6 +54,12 @@ properties: - qcom,sm8650-cpufreq-epss - const: qcom,cpufreq-epss + - description: RIMPS CPUFREQ HW + items: + - enum: + - qcom,shikra-cpufreq-rimps + - const: qcom,cpufreq-rimps + reg: minItems: 1 items: @@ -144,6 +150,7 @@ allOf: - qcom,sc8280xp-cpufreq-epss - qcom,sdm670-cpufreq-hw - qcom,sdm845-cpufreq-hw + - qcom,shikra-cpufreq-rimps - qcom,sm4450-cpufreq-epss - qcom,sm6115-cpufreq-hw - qcom,sm6350-cpufreq-hw From ed49f3e44a35ac0ec3d112d40121ce4ae533783e Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 16:22:49 +0530 Subject: [PATCH 0676/1058] dt-bindings: clock: qcom: Add Shikra Display clock controller Add device tree bindings for the Display clock controller on the Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,shikra-dispcc.yaml | 62 +++++++++++++++++++ .../dt-bindings/clock/qcom,shikra-dispcc.h | 39 ++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml create mode 100644 include/dt-bindings/clock/qcom,shikra-dispcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml new file mode 100644 index 0000000000000..dbaecdd3e0b4b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,shikra-dispcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Display Clock & Reset Controller for Qualcomm Shikra SoC + +maintainers: + - Imran Shaik + +description: | + Display clock control module provides the clocks, resets and power + domains on Qualcomm Shikra SoC platform. + + See also: + - include/dt-bindings/clock/qcom,shikra-dispcc.h + +properties: + compatible: + enum: + - qcom,shikra-dispcc + + clocks: + items: + - description: Board XO source + - description: Board sleep clock + - description: GPLL0 DISP DIV clock from GCC + - description: Byte clock from DSI PHY0 + - description: Pixel clock from DSI PHY0 + - description: Byte clock from DSI PHY1 + - description: Pixel clock from DSI PHY1 + +required: + - compatible + - clocks + - '#power-domain-cells' + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + clock-controller@5f00000 { + compatible = "qcom,shikra-dispcc"; + reg = <0x5f00000 0x20000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, + <&dsi0_phy 0>, + <&dsi0_phy 1>, + <&dsi1_phy 0>, + <&dsi1_phy 1>; + #clock-cells = <1>; + #power-domain-cells = <1>; + #reset-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,shikra-dispcc.h b/include/dt-bindings/clock/qcom,shikra-dispcc.h new file mode 100644 index 0000000000000..088a7c692ad5d --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-dispcc.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_DISP_CC_SHIKRA_H + +/* DISP_CC clocks */ +#define DISP_CC_PLL0 0 +#define DISP_CC_MDSS_AHB_CLK 1 +#define DISP_CC_MDSS_AHB_CLK_SRC 2 +#define DISP_CC_MDSS_BYTE0_CLK 3 +#define DISP_CC_MDSS_BYTE0_CLK_SRC 4 +#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 5 +#define DISP_CC_MDSS_BYTE0_INTF_CLK 6 +#define DISP_CC_MDSS_ESC0_CLK 7 +#define DISP_CC_MDSS_ESC0_CLK_SRC 8 +#define DISP_CC_MDSS_MDP_CLK 9 +#define DISP_CC_MDSS_MDP_CLK_SRC 10 +#define DISP_CC_MDSS_MDP_LUT_CLK 11 +#define DISP_CC_MDSS_NON_GDSC_AHB_CLK 12 +#define DISP_CC_MDSS_PCLK0_CLK 13 +#define DISP_CC_MDSS_PCLK0_CLK_SRC 14 +#define DISP_CC_MDSS_VSYNC_CLK 15 +#define DISP_CC_MDSS_VSYNC_CLK_SRC 16 +#define DISP_CC_SLEEP_CLK 17 +#define DISP_CC_SLEEP_CLK_SRC 18 +#define DISP_CC_XO_CLK 19 +#define DISP_CC_XO_CLK_SRC 20 + +/* DISP_CC power domains */ +#define DISP_CC_MDSS_CORE_GDSC 0 + +/* DISP_CC resets */ +#define DISP_CC_MDSS_CORE_BCR 0 +#define DISP_CC_MDSS_RSCC_BCR 1 + +#endif From 6621f5eada032273c2c884d28000654ee42fde06 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 12:04:44 +0530 Subject: [PATCH 0677/1058] dt-bindings: clock: qcom: Add Shikra GPU clock controller Add device tree bindings for the GPU clock controller on the Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,sm6115-gpucc.yaml | 6 ++- include/dt-bindings/clock/qcom,shikra-gpucc.h | 37 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/qcom,shikra-gpucc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml index 104ba10ca5737..1f6b5cec4642a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml @@ -8,16 +8,20 @@ title: Qualcomm Graphics Clock & Reset Controller on SM6115 maintainers: - Konrad Dybcio + - Imran Shaik description: | Qualcomm graphics clock control module provides clocks, resets and power domains on Qualcomm SoCs. - See also: include/dt-bindings/clock/qcom,sm6115-gpucc.h + See also: + include/dt-bindings/clock/qcom,shikra-gpucc.h + include/dt-bindings/clock/qcom,sm6115-gpucc.h properties: compatible: enum: + - qcom,shikra-gpucc - qcom,sm6115-gpucc clocks: diff --git a/include/dt-bindings/clock/qcom,shikra-gpucc.h b/include/dt-bindings/clock/qcom,shikra-gpucc.h new file mode 100644 index 0000000000000..60714f6cc6cd2 --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-gpucc.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SHIKRA_H + +/* GPU_CC clocks */ +#define GPU_CC_PLL0 0 +#define GPU_CC_AHB_CLK 1 +#define GPU_CC_CRC_AHB_CLK 2 +#define GPU_CC_CX_GFX3D_CLK 3 +#define GPU_CC_CX_GFX3D_SLV_CLK 4 +#define GPU_CC_CX_GMU_CLK 5 +#define GPU_CC_CX_SNOC_DVM_CLK 6 +#define GPU_CC_CXO_AON_CLK 7 +#define GPU_CC_CXO_CLK 8 +#define GPU_CC_GMU_CLK_SRC 9 +#define GPU_CC_GPU_SMMU_VOTE_CLK 10 +#define GPU_CC_GX_CXO_CLK 11 +#define GPU_CC_GX_GFX3D_CLK 12 +#define GPU_CC_GX_GFX3D_CLK_SRC 13 +#define GPU_CC_SLEEP_CLK 14 + +/* GPU_CC power domains */ +#define GPU_CC_CX_GDSC 0 +#define GPU_CC_GX_GDSC 1 + +/* GPU_CC resets */ +#define GPU_CC_CX_BCR 0 +#define GPU_CC_GFX3D_AON_BCR 1 +#define GPU_CC_GMU_BCR 2 +#define GPU_CC_GX_BCR 3 +#define GPU_CC_XO_BCR 4 + +#endif From 96200fee9816def2db08415f3504b5c153d1020d Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 21:38:06 +0530 Subject: [PATCH 0678/1058] clk: qcom: Add support for Display Clock Controller on Shikra Add a driver for the Display clock controller on Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- drivers/clk/qcom/Kconfig | 10 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/dispcc-shikra.c | 565 +++++++++++++++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 drivers/clk/qcom/dispcc-shikra.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index ddf24fef01ed9..e79084a04f92f 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -155,6 +155,16 @@ config CLK_NORD_GCC SPI, I2C, USB, SD/UFS, PCIe etc. The clock controller is a combination of GCC, SE_GCC, NE_GCC and NW_GCC. +config CLK_SHIKRA_DISPCC + tristate "Shikra Display Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_SHIKRA_GCC + help + Support for the display clock controller on Qualcomm Technologies, Inc + Shikra devices. + Say Y if you want to support display devices and functionality such as + splash screen. + config CLK_SHIKRA_GCC tristate "Shikra Global Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 9c01451580d52..3bc396881d9a4 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_KAANAPALI_TCSRCC) += tcsrcc-kaanapali.o obj-$(CONFIG_CLK_KAANAPALI_VIDEOCC) += videocc-kaanapali.o obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o +obj-$(CONFIG_CLK_SHIKRA_DISPCC) += dispcc-shikra.o obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o diff --git a/drivers/clk/qcom/dispcc-shikra.c b/drivers/clk/qcom/dispcc-shikra.c new file mode 100644 index 0000000000000..f4ae20f190465 --- /dev/null +++ b/drivers/clk/qcom/dispcc-shikra.c @@ -0,0 +1,565 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_GPLL0, + DT_DSI0_PHY_PLL_OUT_BYTECLK, + DT_DSI0_PHY_PLL_OUT_DSICLK, + DT_DSI1_PHY_PLL_OUT_BYTECLK, + DT_DSI1_PHY_PLL_OUT_DSICLK, +}; + +enum { + P_BI_TCXO, + P_DISP_CC_PLL0_OUT_MAIN, + P_DSI0_PHY_PLL_OUT_BYTECLK, + P_DSI0_PHY_PLL_OUT_DSICLK, + P_DSI1_PHY_PLL_OUT_DSICLK, + P_GPLL0_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco spark_vco[] = { + { 500000000, 1000000000, 2 }, +}; + +/* 768.0 MHz Configuration */ +static const struct alpha_pll_config disp_cc_pll0_config = { + .l = 0x28, + .alpha = 0x0, + .alpha_en_mask = BIT(24), + .vco_val = BIT(21), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, +}; + +static struct clk_alpha_pll disp_cc_pll0 = { + .offset = 0x0, + .config = &disp_cc_pll0_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct parent_map disp_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, +}; + +static const struct parent_map disp_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map disp_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .index = DT_GPLL0 }, +}; + +static const struct parent_map disp_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_DISP_CC_PLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &disp_cc_pll0.clkr.hw }, + { .index = DT_GPLL0 }, +}; + +static const struct parent_map disp_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, + { P_DSI1_PHY_PLL_OUT_DSICLK, 2 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_DSICLK }, + { .index = DT_DSI1_PHY_PLL_OUT_DSICLK }, +}; + +static const struct parent_map disp_cc_parent_map_5[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_5[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = { + .cmd_rcgr = 0x2154, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_2, + .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_ahb_clk_src", + .parent_data = disp_cc_parent_data_2, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { + .cmd_rcgr = 0x20a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_byte0_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .flags = CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT, + .ops = &clk_byte2_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { + .cmd_rcgr = 0x20c0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_esc0_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(307200000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + F(384000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = { + .cmd_rcgr = 0x2074, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, + .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_mdp_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { + .cmd_rcgr = 0x205c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = disp_cc_parent_map_4, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_pclk0_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), + .flags = CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT, + .ops = &clk_pixel_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = { + .cmd_rcgr = 0x208c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_vsync_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = { + F(32764, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_sleep_clk_src = { + .cmd_rcgr = 0x6050, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_5, + .freq_tbl = ftbl_disp_cc_sleep_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_sleep_clk_src", + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_xo_clk_src = { + .cmd_rcgr = 0x6034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_xo_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { + .reg = 0x20bc, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_byte0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_byte0_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_branch disp_cc_mdss_ahb_clk = { + .halt_reg = 0x2044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte0_clk = { + .halt_reg = 0x201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x201c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_byte0_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_byte0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte0_intf_clk = { + .halt_reg = 0x2020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_byte0_intf_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_byte0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_esc0_clk = { + .halt_reg = 0x2024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_esc0_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_esc0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_mdp_clk = { + .halt_reg = 0x2008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_mdp_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_mdp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_mdp_lut_clk = { + .halt_reg = 0x2010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x2010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_mdp_lut_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_mdp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = { + .halt_reg = 0x4004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_non_gdsc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_pclk0_clk = { + .halt_reg = 0x2004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_pclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_pclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_vsync_clk = { + .halt_reg = 0x2018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_vsync_clk", + .parent_hws = (const struct clk_hw*[]) { + &disp_cc_mdss_vsync_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc disp_cc_mdss_core_gdsc = { + .gdscr = 0x3000, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "disp_cc_mdss_core_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *disp_cc_shikra_clocks[] = { + [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr, + [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr, + [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr, + [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, + [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, + [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr, + [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr, + [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr, + [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr, + [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr, + [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr, + [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr, + [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr, + [DISP_CC_PLL0] = &disp_cc_pll0.clkr, + [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, + [DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr, +}; + +static struct gdsc *disp_cc_shikra_gdscs[] = { + [DISP_CC_MDSS_CORE_GDSC] = &disp_cc_mdss_core_gdsc, +}; + +static const struct qcom_reset_map disp_cc_shikra_resets[] = { + [DISP_CC_MDSS_CORE_BCR] = { 0x2000 }, + [DISP_CC_MDSS_RSCC_BCR] = { 0x4000 }, +}; + +static struct clk_alpha_pll *disp_cc_shikra_plls[] = { + &disp_cc_pll0, +}; + +static u32 disp_cc_shikra_critical_cbcrs[] = { + 0x6068, /* DISP_CC_SLEEP_CLK */ + 0x604c, /* DISP_CC_XO_CLK */ +}; + +static const struct regmap_config disp_cc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x10000, + .fast_io = true, +}; + +static struct qcom_cc_driver_data disp_cc_shikra_driver_data = { + .alpha_plls = disp_cc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(disp_cc_shikra_plls), + .clk_cbcrs = disp_cc_shikra_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(disp_cc_shikra_critical_cbcrs), +}; + +static const struct qcom_cc_desc disp_cc_shikra_desc = { + .config = &disp_cc_shikra_regmap_config, + .clks = disp_cc_shikra_clocks, + .num_clks = ARRAY_SIZE(disp_cc_shikra_clocks), + .resets = disp_cc_shikra_resets, + .num_resets = ARRAY_SIZE(disp_cc_shikra_resets), + .gdscs = disp_cc_shikra_gdscs, + .num_gdscs = ARRAY_SIZE(disp_cc_shikra_gdscs), + .driver_data = &disp_cc_shikra_driver_data, +}; + +static const struct of_device_id disp_cc_shikra_match_table[] = { + { .compatible = "qcom,shikra-dispcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, disp_cc_shikra_match_table); + +static int disp_cc_shikra_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &disp_cc_shikra_desc); +} + +static struct platform_driver disp_cc_shikra_driver = { + .probe = disp_cc_shikra_probe, + .driver = { + .name = "dispcc-shikra", + .of_match_table = disp_cc_shikra_match_table, + }, +}; + +module_platform_driver(disp_cc_shikra_driver); + +MODULE_DESCRIPTION("QTI DISPCC Shikra Driver"); +MODULE_LICENSE("GPL"); From cbbec359311c12d62d8945caf2d0e3bd58adfe23 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 11:45:15 +0530 Subject: [PATCH 0679/1058] clk: qcom: Add support for GPU Clock Controller on Shikra Add a driver for the GPU clock controller on Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-shikra.c | 408 ++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+) create mode 100644 drivers/clk/qcom/gpucc-shikra.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index e79084a04f92f..31b4358c1c2e4 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -174,6 +174,15 @@ config CLK_SHIKRA_GCC Say Y if you want to use multimedia devices or peripheral devices such as Camera, Video, UART, SPI, I2C, USB, SD/eMMC etc. +config CLK_SHIKRA_GPUCC + tristate "Shikra Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_SHIKRA_GCC + help + Support for the graphics clock controller on Shikra devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config CLK_X1E80100_CAMCC tristate "X1E80100 Camera Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 3bc396881d9a4..7be66d73c29c0 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o obj-$(CONFIG_CLK_SHIKRA_DISPCC) += dispcc-shikra.o obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o +obj-$(CONFIG_CLK_SHIKRA_GPUCC) += gpucc-shikra.o obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_GCC) += gcc-x1e80100.o diff --git a/drivers/clk/qcom/gpucc-shikra.c b/drivers/clk/qcom/gpucc-shikra.c new file mode 100644 index 0000000000000..19a938a14d68d --- /dev/null +++ b/drivers/clk/qcom/gpucc-shikra.c @@ -0,0 +1,408 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_GPLL0_OUT_MAIN, + DT_GPLL0_OUT_MAIN_DIV, +}; + +enum { + P_BI_TCXO, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_2X_DIV_CLK_SRC, + P_GPU_CC_PLL0_OUT_AUX, + P_GPU_CC_PLL0_OUT_AUX2, + P_GPU_CC_PLL0_OUT_MAIN, +}; + +static const struct pll_vco huayra_vco[] = { + { 600000000, 3300000000, 0 }, + { 600000000, 2200000000, 1 }, +}; + +/* 710.4 MHz Configuration */ +static const struct alpha_pll_config gpu_cc_pll0_config = { + .l = 0x25, + .cal_l = 0x4e, + .alpha = 0x0, + .config_ctl_val = 0x200d4828, + .config_ctl_hi_val = 0x6, + .config_ctl_hi1_val = 0x00000000, + .test_ctl_val = 0x1c000000, + .test_ctl_hi_val = 0x00004000, + .test_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0xf, +}; + +static struct clk_alpha_pll gpu_cc_pll0 = { + .offset = 0x0, + .config = &gpu_cc_pll0_config, + .vco_table = huayra_vco, + .num_vco = ARRAY_SIZE(huayra_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_huayra_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_2X_DIV_CLK_SRC, 1 }, + { P_GPU_CC_PLL0_OUT_AUX2, 2 }, + { P_GPU_CC_PLL0_OUT_AUX, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x1120, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { + F(355200000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(537600000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(672000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(844800000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(921600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1017600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1142400000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { + .cmd_rcgr = 0x101c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gx_gfx3d_clk_src", + .parent_data = gpu_cc_parent_data_1, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x107c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x107c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_crc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gfx3d_clk = { + .halt_reg = 0x10a4, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x10a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gfx3d_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = { + .halt_reg = 0x10a8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x10a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gfx3d_slv_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x1098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1098, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { + .halt_reg = 0x108c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x108c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_snoc_dvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x109c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x109c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cxo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gpu_smmu_vote_clk = { + .halt_reg = 0x5000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gpu_smmu_vote_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gfx3d_clk = { + .halt_reg = 0x1054, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gx_gfx3d_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x1090, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1090, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cc_cx_gdsc = { + .gdscr = 0x106c, + .gds_hw_ctrl = 0x1540, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gpu_cc_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE | VOTABLE, +}; + +static struct gdsc gpu_cc_gx_gdsc = { + .gdscr = 0x100c, + .clamp_io_ctrl = 0x1508, + .resets = (unsigned int []){ GPU_CC_GX_BCR }, + .reset_count = 1, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gpu_cc_gx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | SW_RESET | CLAMP_IO | AON_RESET, +}; + +static struct clk_regmap *gpu_cc_shikra_clocks[] = { + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, + [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_GPU_SMMU_VOTE_CLK] = &gpu_cc_gpu_smmu_vote_clk.clkr, + [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, + [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, +}; + +static struct gdsc *gpu_cc_shikra_gdscs[] = { + [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, + [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc, +}; + +static const struct qcom_reset_map gpu_cc_shikra_resets[] = { + [GPU_CC_CX_BCR] = { 0x1068 }, + [GPU_CC_GFX3D_AON_BCR] = { 0x10a0 }, + [GPU_CC_GMU_BCR] = { 0x111c }, + [GPU_CC_GX_BCR] = { 0x1008 }, + [GPU_CC_XO_BCR] = { 0x1000 }, +}; + +static struct clk_alpha_pll *gpu_cc_shikra_plls[] = { + &gpu_cc_pll0, +}; + +static u32 gpu_cc_shikra_critical_cbcrs[] = { + 0x1078, /* GPU_CC_AHB_CLK */ + 0x1004, /* GPU_CC_CXO_AON_CLK */ + 0x1060, /* GPU_CC_GX_CXO_CLK */ +}; + +static const struct regmap_config gpu_cc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x7008, + .fast_io = true, +}; + +static struct qcom_cc_driver_data gpu_cc_shikra_driver_data = { + .alpha_plls = gpu_cc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(gpu_cc_shikra_plls), + .clk_cbcrs = gpu_cc_shikra_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_shikra_critical_cbcrs), +}; + +static const struct qcom_cc_desc gpu_cc_shikra_desc = { + .config = &gpu_cc_shikra_regmap_config, + .clks = gpu_cc_shikra_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_shikra_clocks), + .resets = gpu_cc_shikra_resets, + .num_resets = ARRAY_SIZE(gpu_cc_shikra_resets), + .gdscs = gpu_cc_shikra_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_shikra_gdscs), + .driver_data = &gpu_cc_shikra_driver_data, +}; + +static const struct of_device_id gpu_cc_shikra_match_table[] = { + { .compatible = "qcom,shikra-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_shikra_match_table); + +static int gpu_cc_shikra_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &gpu_cc_shikra_desc); +} + +static struct platform_driver gpu_cc_shikra_driver = { + .probe = gpu_cc_shikra_probe, + .driver = { + .name = "gpucc-shikra", + .of_match_table = gpu_cc_shikra_match_table, + }, +}; + +module_platform_driver(gpu_cc_shikra_driver); + +MODULE_DESCRIPTION("QTI GPUCC Shikra Driver"); +MODULE_LICENSE("GPL"); From 4cb774b85f95a658791eca2a137ffd65d3443016 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 13:31:00 +0530 Subject: [PATCH 0680/1058] arm64: defconfig: Enable DISPCC and GPUCC on Shikra EVK boards Enable the DISPCC and GPUCC drivers on the Qualcomm Shikra EVK boards. Signed-off-by: Imran Shaik --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index ac82018addff9..21f3a52f9f76e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1446,7 +1446,9 @@ CONFIG_CLK_IMX8QXP=y CONFIG_CLK_IMX8ULP=y CONFIG_CLK_IMX93=y CONFIG_CLK_IMX95_BLK_CTL=y +CONFIG_CLK_SHIKRA_DISPCC=y CONFIG_CLK_SHIKRA_GCC=y +CONFIG_CLK_SHIKRA_GPUCC=y CONFIG_TI_SCI_CLK=y CONFIG_COMMON_CLK_MT8192_AUDSYS=y CONFIG_COMMON_CLK_MT8192_CAMSYS=y From 84a7fde9377671b89b54bafaa6bf08f67acce663 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Thu, 30 Apr 2026 14:50:07 +0530 Subject: [PATCH 0681/1058] FROMLIST: pinctrl: qcom: Unconditionally mark gpio as wakeup enable The wakeup enable bit needs to be set irrespective of the SoC using PDC or MPM as wakeup capable irqchip to allow the GPIO interrupts to be forwarded to parent irqchip. This is set only for PDC irqchip using additional check skip_wake_irqs making it impossible for MPM irqchip to detect the GPIO interrupt during SoC low power mode since for MPM irqchip the skip_wake_irqs is always false. Remove skip_wake_irqs condition when setting wakeup enable bit to allow forwarding GPIO interrupts for SoCs using MPM irqchip too. Fixes: 76b446f5b86e ("pinctrl: qcom: handle intr_target_reg wakeup_present/enable bits") Signed-off-by: Sneh Mankad Reviewed-by: Maulik Shah Link: https://lore.kernel.org/r/20260430-enable_wakeup_capable_gpios-v2-1-8c26ac795318@oss.qualcomm.com --- drivers/pinctrl/qcom/pinctrl-msm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 11db6564c44df..fd0add4e71da1 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1240,12 +1240,12 @@ static int msm_gpio_irq_reqres(struct irq_data *d) /* * If the wakeup_enable bit is present and marked as available for the * requested GPIO, it should be enabled when the GPIO is marked as - * wake irq in order to allow the interrupt event to be transfered to - * the PDC HW. + * wake irq in order to allow the interrupt event to be transferred to + * the PDC/MPM HW. * While the name implies only the wakeup event, it's also required for * the interrupt event. */ - if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { + if (g->intr_wakeup_present_bit) { u32 intr_cfg; raw_spin_lock_irqsave(&pctrl->lock, flags); @@ -1273,7 +1273,7 @@ static void msm_gpio_irq_relres(struct irq_data *d) unsigned long flags; /* Disable the wakeup_enable bit if it has been set in msm_gpio_irq_reqres() */ - if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { + if (g->intr_wakeup_present_bit) { u32 intr_cfg; raw_spin_lock_irqsave(&pctrl->lock, flags); From 815e8af5960956de3dbb4c4ceeabd56926935947 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 5 May 2026 16:22:30 +0530 Subject: [PATCH 0682/1058] dt-bindings: clock: qcom: Add GCC_QUSB2PHY_SEC_BCR support for Shikra Add GCC_QUSB2PHY_SEC_BCR reset support for Shikra platform. Signed-off-by: Imran Shaik --- include/dt-bindings/clock/qcom,shikra-gcc.h | 23 +++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/include/dt-bindings/clock/qcom,shikra-gcc.h b/include/dt-bindings/clock/qcom,shikra-gcc.h index 77c6159755ce9..2e88a9cd9f535 100644 --- a/include/dt-bindings/clock/qcom,shikra-gcc.h +++ b/include/dt-bindings/clock/qcom,shikra-gcc.h @@ -243,16 +243,17 @@ #define GCC_PDM_BCR 9 #define GCC_QUPV3_WRAPPER_0_BCR 10 #define GCC_QUSB2PHY_PRIM_BCR 11 -#define GCC_SDCC1_BCR 12 -#define GCC_SDCC2_BCR 13 -#define GCC_TSCSS_BCR 14 -#define GCC_USB20_BCR 15 -#define GCC_USB30_PRIM_BCR 16 -#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 17 -#define GCC_USB3_PHY_PRIM_SP0_BCR 18 -#define GCC_USB_PHY_CFG_AHB2PHY_BCR 19 -#define GCC_VCODEC0_BCR 20 -#define GCC_VENUS_BCR 21 -#define GCC_VIDEO_INTERFACE_BCR 22 +#define GCC_QUSB2PHY_SEC_BCR 12 +#define GCC_SDCC1_BCR 13 +#define GCC_SDCC2_BCR 14 +#define GCC_TSCSS_BCR 15 +#define GCC_USB20_BCR 16 +#define GCC_USB30_PRIM_BCR 17 +#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 18 +#define GCC_USB3_PHY_PRIM_SP0_BCR 19 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 20 +#define GCC_VCODEC0_BCR 21 +#define GCC_VENUS_BCR 22 +#define GCC_VIDEO_INTERFACE_BCR 23 #endif From 0cbfa76395e6927087a9eecdad4b031643488362 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 5 May 2026 16:24:13 +0530 Subject: [PATCH 0683/1058] clk: qcom: gcc-shikra: Update GCC driver for Shikra Add GCC_QUSB2PHY_SEC_BCR reset support for Shikra. While at it, drop the flags which are not required for the fixed parent clocks. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gcc-shikra.c | 114 +++++++++------------------------- 1 file changed, 29 insertions(+), 85 deletions(-) diff --git a/drivers/clk/qcom/gcc-shikra.c b/drivers/clk/qcom/gcc-shikra.c index 3ca5ed7cd48a1..8834618354882 100644 --- a/drivers/clk/qcom/gcc-shikra.c +++ b/drivers/clk/qcom/gcc-shikra.c @@ -68,9 +68,12 @@ static const struct pll_vco brammo_vco[] = { { 500000000, 1250000000, 0 }, }; +static const struct pll_vco default_vco[] = { + { 500000000, 1000000000, 2 }, +}; + static const struct pll_vco spark_vco[] = { { 750000000, 1500000000, 1 }, - { 500000000, 1000000000, 2 }, }; static struct clk_alpha_pll gpll0 = { @@ -112,23 +115,6 @@ static struct clk_alpha_pll_postdiv gpll0_out_aux2 = { }, }; -static struct clk_alpha_pll gpll1 = { - .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], - .clkr = { - .enable_reg = 0x79000, - .enable_mask = BIT(1), - .hw.init = &(const struct clk_init_data) { - .name = "gpll1", - .parent_data = &(const struct clk_parent_data) { - .index = DT_BI_TCXO, - }, - .num_parents = 1, - .ops = &clk_alpha_pll_fixed_ops, - }, - }, -}; - /* 1152.0 MHz Configuration */ static const struct alpha_pll_config gpll10_config = { .l = 0x3c, @@ -176,9 +162,10 @@ static const struct alpha_pll_config gpll11_config = { static struct clk_alpha_pll gpll11 = { .offset = 0xb000, .config = &gpll11_config, - .vco_table = spark_vco, - .num_vco = ARRAY_SIZE(spark_vco), + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .flags = SUPPORTS_DYNAMIC_UPDATE, .clkr = { .enable_reg = 0x79000, .enable_mask = BIT(11), @@ -380,9 +367,10 @@ static const struct alpha_pll_config gpll8_config = { static struct clk_alpha_pll gpll8 = { .offset = 0x8000, .config = &gpll8_config, - .vco_table = spark_vco, - .num_vco = ARRAY_SIZE(spark_vco), + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .flags = SUPPORTS_DYNAMIC_UPDATE, .clkr = { .enable_reg = 0x79000, .enable_mask = BIT(8), @@ -464,9 +452,9 @@ static struct clk_alpha_pll_postdiv gpll9_out_main = { .num_post_div = ARRAY_SIZE(post_div_table_gpll9_out_main), .width = 2, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO_EVO], - .clkr.hw.init = &(const struct clk_init_data){ + .clkr.hw.init = &(const struct clk_init_data) { .name = "gpll9_out_main", - .parent_hws = (const struct clk_hw*[]){ + .parent_hws = (const struct clk_hw*[]) { &gpll9.clkr.hw, }, .num_parents = 1, @@ -529,7 +517,7 @@ static const struct clk_parent_data gcc_parent_data_3[] = { { .hw = &gpll0.clkr.hw }, { .hw = &gpll9.clkr.hw }, { .hw = &gpll10.clkr.hw }, - { .hw = &gpll9.clkr.hw }, + { .hw = &gpll9_out_main.clkr.hw }, { .hw = &gpll3_out_main.clkr.hw }, }; @@ -874,7 +862,6 @@ static struct clk_rcg2 gcc_camss_axi_clk_src = { .name = "gcc_camss_axi_clk_src", .parent_data = gcc_parent_data_5, .num_parents = ARRAY_SIZE(gcc_parent_data_5), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -896,7 +883,6 @@ static struct clk_rcg2 gcc_camss_cci_clk_src = { .name = "gcc_camss_cci_clk_src", .parent_data = gcc_parent_data_14, .num_parents = ARRAY_SIZE(gcc_parent_data_14), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -920,7 +906,6 @@ static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { .name = "gcc_camss_csi0phytimer_clk_src", .parent_data = gcc_parent_data_6, .num_parents = ARRAY_SIZE(gcc_parent_data_6), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -936,7 +921,6 @@ static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { .name = "gcc_camss_csi1phytimer_clk_src", .parent_data = gcc_parent_data_6, .num_parents = ARRAY_SIZE(gcc_parent_data_6), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1030,7 +1014,6 @@ static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = { .name = "gcc_camss_ope_ahb_clk_src", .parent_data = gcc_parent_data_7, .num_parents = ARRAY_SIZE(gcc_parent_data_7), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1117,7 +1100,6 @@ static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = { .name = "gcc_camss_tfe_0_csid_clk_src", .parent_data = gcc_parent_data_9, .num_parents = ARRAY_SIZE(gcc_parent_data_9), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1133,7 +1115,6 @@ static struct clk_rcg2 gcc_camss_tfe_1_clk_src = { .name = "gcc_camss_tfe_1_clk_src", .parent_data = gcc_parent_data_8, .num_parents = ARRAY_SIZE(gcc_parent_data_8), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1149,7 +1130,6 @@ static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = { .name = "gcc_camss_tfe_1_csid_clk_src", .parent_data = gcc_parent_data_9, .num_parents = ARRAY_SIZE(gcc_parent_data_9), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1173,7 +1153,6 @@ static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = { .name = "gcc_camss_tfe_cphy_rx_clk_src", .parent_data = gcc_parent_data_15, .num_parents = ARRAY_SIZE(gcc_parent_data_15), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1196,7 +1175,6 @@ static struct clk_rcg2 gcc_camss_top_ahb_clk_src = { .name = "gcc_camss_top_ahb_clk_src", .parent_data = gcc_parent_data_5, .num_parents = ARRAY_SIZE(gcc_parent_data_5), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1221,7 +1199,6 @@ static struct clk_rcg2 gcc_emac0_axi_clk_src = { .name = "gcc_emac0_axi_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1242,7 +1219,6 @@ static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = { .name = "gcc_emac0_phy_aux_clk_src", .parent_data = gcc_parent_data_10, .num_parents = ARRAY_SIZE(gcc_parent_data_10), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1263,7 +1239,6 @@ static struct clk_rcg2 gcc_emac0_ptp_clk_src = { .name = "gcc_emac0_ptp_clk_src", .parent_data = gcc_parent_data_11, .num_parents = ARRAY_SIZE(gcc_parent_data_11), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1286,7 +1261,6 @@ static struct clk_rcg2 gcc_emac0_rgmii_clk_src = { .name = "gcc_emac0_rgmii_clk_src", .parent_data = gcc_parent_data_12, .num_parents = ARRAY_SIZE(gcc_parent_data_12), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1302,7 +1276,6 @@ static struct clk_rcg2 gcc_emac1_axi_clk_src = { .name = "gcc_emac1_axi_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1318,7 +1291,6 @@ static struct clk_rcg2 gcc_emac1_phy_aux_clk_src = { .name = "gcc_emac1_phy_aux_clk_src", .parent_data = gcc_parent_data_10, .num_parents = ARRAY_SIZE(gcc_parent_data_10), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1334,7 +1306,6 @@ static struct clk_rcg2 gcc_emac1_ptp_clk_src = { .name = "gcc_emac1_ptp_clk_src", .parent_data = gcc_parent_data_11, .num_parents = ARRAY_SIZE(gcc_parent_data_11), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1350,7 +1321,6 @@ static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { .name = "gcc_emac1_rgmii_clk_src", .parent_data = gcc_parent_data_12, .num_parents = ARRAY_SIZE(gcc_parent_data_12), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1374,7 +1344,6 @@ static struct clk_rcg2 gcc_gp1_clk_src = { .name = "gcc_gp1_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1390,7 +1359,6 @@ static struct clk_rcg2 gcc_gp2_clk_src = { .name = "gcc_gp2_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1406,7 +1374,6 @@ static struct clk_rcg2 gcc_gp3_clk_src = { .name = "gcc_gp3_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1422,7 +1389,6 @@ static struct clk_rcg2 gcc_pcie_aux_clk_src = { .name = "gcc_pcie_aux_clk_src", .parent_data = gcc_parent_data_4, .num_parents = ARRAY_SIZE(gcc_parent_data_4), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1438,7 +1404,6 @@ static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = { .name = "gcc_pcie_aux_phy_clk_src", .parent_data = gcc_parent_data_4, .num_parents = ARRAY_SIZE(gcc_parent_data_4), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1459,7 +1424,6 @@ static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = { .name = "gcc_pcie_rchng_phy_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1481,7 +1445,6 @@ static struct clk_rcg2 gcc_pdm2_clk_src = { .name = "gcc_pdm2_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1510,7 +1473,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1528,7 +1490,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1546,7 +1507,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1564,7 +1524,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1582,7 +1541,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1600,7 +1558,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1618,7 +1575,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { .name = "gcc_qupv3_wrap0_s6_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1636,7 +1592,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { .name = "gcc_qupv3_wrap0_s7_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1654,7 +1609,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s8_clk_src_init = { .name = "gcc_qupv3_wrap0_s8_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1672,7 +1626,6 @@ static struct clk_init_data gcc_qupv3_wrap0_s9_clk_src_init = { .name = "gcc_qupv3_wrap0_s9_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }; @@ -1709,7 +1662,6 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { .name = "gcc_sdcc1_apps_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_floor_ops, }, }; @@ -1734,7 +1686,6 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { .name = "gcc_sdcc1_ice_core_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_floor_ops, }, }; @@ -1760,7 +1711,6 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { .name = "gcc_sdcc2_apps_clk_src", .parent_data = gcc_parent_data_21, .num_parents = ARRAY_SIZE(gcc_parent_data_21), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_floor_ops, }, }; @@ -1776,7 +1726,6 @@ static struct clk_rcg2 gcc_tscss_clk_src = { .name = "gcc_tscss_clk_src", .parent_data = gcc_parent_data_22, .num_parents = ARRAY_SIZE(gcc_parent_data_22), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1798,7 +1747,6 @@ static struct clk_rcg2 gcc_usb20_master_clk_src = { .name = "gcc_usb20_master_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1814,7 +1762,6 @@ static struct clk_rcg2 gcc_usb20_mock_utmi_clk_src = { .name = "gcc_usb20_mock_utmi_clk_src", .parent_data = gcc_parent_data_13, .num_parents = ARRAY_SIZE(gcc_parent_data_13), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1838,7 +1785,6 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { .name = "gcc_usb30_prim_master_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1854,7 +1800,6 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { .name = "gcc_usb30_prim_mock_utmi_clk_src", .parent_data = gcc_parent_data_0, .num_parents = ARRAY_SIZE(gcc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1870,7 +1815,6 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { .name = "gcc_usb3_prim_phy_aux_clk_src", .parent_data = gcc_parent_data_4, .num_parents = ARRAY_SIZE(gcc_parent_data_4), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_shared_ops, }, }; @@ -1899,6 +1843,20 @@ static struct clk_rcg2 gcc_video_venus_clk_src = { }, }; +static struct clk_regmap_div gcc_disp_gpll0_clk_src = { + .reg = 0x17058, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + static struct clk_regmap_div gcc_usb20_mock_utmi_postdiv_clk_src = { .reg = 0xb0038, .shift = 0, @@ -2487,20 +2445,6 @@ static struct clk_branch gcc_ddrss_memnoc_pcie_sf_clk = { }, }; -static struct clk_regmap_div gcc_disp_gpll0_clk_src = { - .reg = 0x17058, - .shift = 0, - .width = 2, - .clkr.hw.init = &(struct clk_init_data) { - .name = "gcc_disp_gpll0_clk_src", - .parent_hws = (const struct clk_hw*[]){ - &gpll0.clkr.hw, - }, - .num_parents = 1, - .ops = &clk_regmap_div_ops, - }, -}; - static struct clk_branch gcc_disp_gpll0_div_clk_src = { .halt_check = BRANCH_HALT_DELAY, .clkr = { @@ -4334,7 +4278,6 @@ static struct clk_regmap *gcc_shikra_clocks[] = { [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, [GPLL0] = &gpll0.clkr, [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr, - [GPLL1] = &gpll1.clkr, [GPLL10] = &gpll10.clkr, [GPLL11] = &gpll11.clkr, [GPLL12] = &gpll12.clkr, @@ -4376,6 +4319,7 @@ static const struct qcom_reset_map gcc_shikra_resets[] = { [GCC_PDM_BCR] = { 0x20000 }, [GCC_QUPV3_WRAPPER_0_BCR] = { 0x1f000 }, [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1c004 }, [GCC_SDCC1_BCR] = { 0x38000 }, [GCC_SDCC2_BCR] = { 0x1e000 }, [GCC_TSCSS_BCR] = { 0xac000 }, @@ -4480,5 +4424,5 @@ static void __exit gcc_shikra_exit(void) } module_exit(gcc_shikra_exit); -MODULE_DESCRIPTION("QTI GCC SHIKRA Driver"); +MODULE_DESCRIPTION("QTI GCC Shikra Driver"); MODULE_LICENSE("GPL"); From 10ec34b524b3669866c890954d2702250ff4d6f5 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 5 May 2026 16:31:00 +0530 Subject: [PATCH 0684/1058] clk: qcom: gpucc-shikra: Drop unused DT_BI_TCXO_AO index Remove the unused enum entry to keep the binding indices aligned with device tree. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gpucc-shikra.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/gpucc-shikra.c b/drivers/clk/qcom/gpucc-shikra.c index 19a938a14d68d..4ad4fc0b6703a 100644 --- a/drivers/clk/qcom/gpucc-shikra.c +++ b/drivers/clk/qcom/gpucc-shikra.c @@ -24,7 +24,6 @@ enum { DT_BI_TCXO, - DT_BI_TCXO_AO, DT_GPLL0_OUT_MAIN, DT_GPLL0_OUT_MAIN_DIV, }; From 7cc24ba9180d2ffd7070243a96ca13e8df4e9b90 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 8 May 2026 10:42:17 +0530 Subject: [PATCH 0685/1058] dt-bindings: clock: qcom: shikra-gcc: Add power-domains property Document the power-domains property in order to propagate the votes on GDSC to CX raill. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,shikra-gcc.yaml | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml index 39cf7383df8bc..da6eebfa84c22 100644 --- a/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml @@ -4,15 +4,15 @@ $id: http://devicetree.org/schemas/clock/qcom,shikra-gcc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm Global Clock & Reset Controller on Shikra +title: Global Clock & Reset Controller on Qualcomm Shikra SoC maintainers: - Imran Shaik - Taniya Das description: | - Qualcomm global clock control module provides the clocks, resets and power - domains on Shikra. + Global clock control module provides the clocks, resets and power + domains on Qualcomm Shikra SoC platform. See also: include/dt-bindings/clock/qcom,shikra-gcc.h @@ -31,9 +31,14 @@ properties: - description: PCIE Pipe clock source - description: USB3 phy wrapper pipe clock source + power-domains: + items: + - description: CX domain + required: - compatible - clocks + - power-domains - '#power-domain-cells' allOf: @@ -44,20 +49,22 @@ unevaluatedProperties: false examples: - | #include + #include clock-controller@1400000 { compatible = "qcom,shikra-gcc"; reg = <0x01400000 0x1f0000>; clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, - <&sleep_clk>, - <&emac0_sgmiiphy_rclk>, - <&emac0_sgmiiphy_tclk>, - <&emac1_sgmiiphy_rclk>, - <&emac1_sgmiiphy_tclk>, - <&pcie_pipe_clk>, - <&usb3_phy_wrapper_gcc_usb30_pipe_clk>; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; + <&sleep_clk>, + <&emac0_sgmiiphy_rclk>, + <&emac0_sgmiiphy_tclk>, + <&emac1_sgmiiphy_rclk>, + <&emac1_sgmiiphy_tclk>, + <&pcie_pipe_clk>, + <&usb3_phy_wrapper_gcc_usb30_pipe_clk>; + power-domains = <&rpmpd RPMPD_VDDCX>; + #clock-cells = <1>; + #power-domain-cells = <1>; + #reset-cells = <1>; }; ... From 10ed810639825c24787d6b791eadb79b35063502 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Fri, 27 Mar 2026 18:14:37 +0530 Subject: [PATCH 0686/1058] dt-bindings: mailbox: qcom: Modify Shikra APCS compatible Mention compatible for the Qualcomm Shikra APCS block in the same block as sdm845-apss-shared since they share the same data. Signed-off-by: Sneh Mankad --- .../devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml index 01d6eaefe165e..1b4ef0688ca79 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml @@ -66,7 +66,6 @@ properties: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared - - qcom,shikra-apcs-hmss-global reg: maxItems: 1 @@ -240,7 +239,6 @@ allOf: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared - - qcom,shikra-apcs-hmss-global then: properties: clocks: false From b123812de7a94ee173673281dab83da9dce63581 Mon Sep 17 00:00:00 2001 From: Anandu Krishnan E Date: Tue, 12 May 2026 13:54:49 +0530 Subject: [PATCH 0687/1058] misc: fastrpc: Introduce cache maintenance operations Introduce cache maintenance operations for remote arguments in fastrpc driver for non-dma coherent targets. Upstream-Status: Pending Signed-off-by: Abhinav Parihar Signed-off-by: Anandu Krishnan E --- drivers/misc/fastrpc.c | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index f3a49384586d1..ada424aa50cd9 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -187,6 +187,7 @@ struct fastrpc_buf_overlap { u64 mstart; u64 mend; u64 offset; + bool do_cmo; }; struct fastrpc_buf { @@ -255,6 +256,7 @@ struct fastrpc_session_ctx { int sid; bool used; bool valid; + bool coherent; }; struct fastrpc_soc_data { @@ -332,6 +334,18 @@ static inline u64 fastrpc_sid_offset(struct fastrpc_channel_ctx *cctx, return (u64)sctx->sid << cctx->soc_data->sid_pos; } +/* + * Align buffer size to kernel page granularity for dma-buf cache maintenance. + */ +static inline uint64_t buf_page_size(uint64_t size) +{ + int cache_align = dma_get_cache_alignment(); + uint64_t sz = ALIGN(size, cache_align); + + return max_t(uint64_t, sz, (uint64_t)cache_align); +} + + static void fastrpc_free_map(struct kref *ref) { struct fastrpc_map *map; @@ -610,7 +624,9 @@ static int olaps_cmp(const void *a, const void *b) static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) { u64 max_end = 0; + int max_raix = -1; int i; + int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); for (i = 0; i < ctx->nbufs; ++i) { ctx->olaps[i].start = ctx->args[i].ptr; @@ -630,6 +646,9 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) if (ctx->olaps[i].end > max_end) { max_end = ctx->olaps[i].end; } else { + if ((max_raix < inbufs && ctx->olaps[i].raix + 1 > inbufs) || + (ctx->olaps[i].raix < inbufs && max_raix + 1 > inbufs)) + ctx->olaps[i].do_cmo = true; ctx->olaps[i].mend = 0; ctx->olaps[i].mstart = 0; } @@ -639,6 +658,7 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) ctx->olaps[i].mstart = ctx->olaps[i].start; ctx->olaps[i].offset = 0; max_end = ctx->olaps[i].end; + max_raix = ctx->olaps[i].raix; } } } @@ -861,7 +881,7 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, err = PTR_ERR(map->attach); goto attach_err; } - + if (!sess->coherent) table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL); if (IS_ERR(table)) { err = PTR_ERR(table); @@ -1019,6 +1039,70 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) return 0; } +static int fastrpc_flush_args(struct fastrpc_invoke_ctx *ctx, + union fastrpc_remote_arg *rpra) +{ + int oix, inbufs, outbufs; + struct device *dev = ctx->fl->sctx->dev; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + for (oix = 0; oix < inbufs+outbufs; ++oix) { + int i = ctx->olaps[oix].raix; + struct fastrpc_map *map = ctx->maps[i]; + + if (i+1 > inbufs) + continue; + if (!map) + continue; + if (rpra[i].buf.len && ctx->olaps[oix].mstart) { + if (map->buf) { + if ((buf_page_size(ctx->olaps[oix].mend - + ctx->olaps[oix].mstart)) == map->size ) { + dma_buf_begin_cpu_access(map->buf, DMA_TO_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } + } + } + return 0; +} + +static int fastrpc_inv_args(struct fastrpc_invoke_ctx *ctx) +{ + int i, inbufs, outbufs; + uint32_t sc = ctx->sc; + union fastrpc_remote_arg *rpra = ctx->rpra; + struct device *dev = ctx->fl->sctx->dev; + + inbufs = REMOTE_SCALARS_INBUFS(sc); + outbufs = REMOTE_SCALARS_OUTBUFS(sc); + for (i = 0; i < inbufs+outbufs; ++i) { + int over = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[over]; + + if (over + 1 <= inbufs) + continue; + if (!rpra[over].buf.len) + continue; + if (!map) + continue; + if (((uintptr_t)rpra & PAGE_MASK) == + ((uintptr_t)rpra[over].buf.pv & PAGE_MASK)) + continue; + if (ctx->olaps[i].mstart) { + if (map->buf) { + if (((buf_page_size(ctx->olaps[i].mend - + ctx->olaps[i].mstart)) == map->size)) { + dma_buf_begin_cpu_access(map->buf, DMA_FROM_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } + } + } + return 0; +} + static struct fastrpc_invoke_buf *fastrpc_invoke_buf_start(union fastrpc_remote_arg *pra, int len) { return (struct fastrpc_invoke_buf *)(&pra[len]); @@ -1139,6 +1223,12 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) } } + if (!ctx->fl->sctx->coherent) { + err = fastrpc_flush_args(ctx, rpra); + if (err) + goto bail; + } + for (i = ctx->nbufs; i < ctx->nscalars; ++i) { list[i].num = ctx->args[i].length ? 1 : 0; list[i].pgidx = i; @@ -1266,6 +1356,11 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; + if (!fl->sctx->coherent) { + err = fastrpc_inv_args(ctx); + if (err) + goto bail; + } /* make sure that all CPU memory writes are seen by DSP */ dma_wmb(); /* Send invoke buffer to remote dsp */ @@ -1285,6 +1380,11 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, /* make sure that all memory writes by DSP are seen by CPU */ dma_rmb(); + if (!fl->sctx->coherent) { + err = fastrpc_inv_args(ctx); + if (err) + goto bail; + } /* populate all the output buffers with results */ err = fastrpc_put_args(ctx, kernel); if (err) @@ -2243,6 +2343,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent"); dev_set_drvdata(dev, sess); if (cctx->domain_id == CDSP_DOMAIN_ID) From e756ed00136c45c156acdd5a84558404aefa6ed6 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Thu, 9 Apr 2026 16:11:55 +0530 Subject: [PATCH 0688/1058] dt-bindings: media: qcom,qcm2290-venus: document shikra Iris compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the Iris video accelerator used on Shikra platforms by adding the qcom,shikra-iris compatible. Although QCM2290 and Shikra share the same video hardware and overall integration, their SMMU programming differs. QCM2290 exposes separate Stream IDs for the video hardware and the Xtensa path, requiring two explicit IOMMU entries, whereas Shikra uses a masked SMR to collapse equivalent Stream IDs into a single mapping. Due to QCM2290’s SID layout and Xtensa isolation requirements, such SMR masking is not applicable on QCM2290 platforms. Since Shikra uses the same video hardware as QCM2290 and shares the same programming model and capabilities, it is added as a fallback compatible to qcom,qcm2290-venus, with conditional handling to allow either one or two IOMMU entries. Signed-off-by: Dikshita Agarwal --- .../bindings/media/qcom,qcm2290-venus.yaml | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml index 5977e7d0a71b4..770dd159c56d1 100644 --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml @@ -15,12 +15,27 @@ description: allOf: - $ref: qcom,venus-common.yaml# + - if: + properties: + compatible: + contains: + const: qcom,shikra-iris + then: + properties: + iommus: + maxItems: 1 + else: + properties: + iommus: + maxItems: 2 properties: compatible: oneOf: - items: - - const: qcom,sm6115-venus + - enum: + - const: qcom,shikra-iris + - const: qcom,sm6115-venus - const: qcom,qcm2290-venus - const: qcom,qcm2290-venus @@ -45,9 +60,6 @@ properties: - const: vcodec0_core - const: vcodec0_bus - iommus: - maxItems: 2 - interconnects: maxItems: 2 From 33818d98f13976ea61d815cf9a78ebb709026185 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 12 May 2026 17:00:31 +0530 Subject: [PATCH 0689/1058] iommu/arm-smmu: Add ACTLR settings for missing MDSS devices for new Shikra platform Shikra being a new platform has a different target specific compatible for mdss device. Add ACTLR configuration for corresponding compatible to apply the required QoS settings. Signed-off-by: Bibek Kumar Patro --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index e2c914fccd6fc..f95b7d3b7a965 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -55,6 +55,8 @@ static const struct of_device_id qcom_smmu_actlr_client_of_match[] = { .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sc8280xp-mdss", .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, + { .compatible = "qcom,shikra-mdss", + .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sm6115-mdss", .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sm6125-mdss", From f1f7eec098f0d24b46824c6060555f039a6dd6b9 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Tue, 5 May 2026 20:12:30 +0530 Subject: [PATCH 0690/1058] dt-bindings: display: msm: qcm2290: Add Shikra MDSS Shikra SoC uses the same MDSS/DPU/DSI hardware as QCM2290 (DPU 6.5), sharing the same register layout, DSI controller and 14nm DSI PHY. Add qcom,shikra-mdss to the qcm2290-mdss binding compatible enum rather than introducing a separate binding file. Register qcom,shikra-dsi-ctrl in dsi-controller-main.yaml alongside qcom,qcm2290-dsi-ctrl, and update the qcm2290-mdss patternProperties to accept both SoC-specific DPU and DSI controller compatibles. Signed-off-by: Mahadevan P --- .../display/msm/dsi-controller-main.yaml | 1 + .../display/msm/qcom,qcm2290-dpu.yaml | 4 ++- .../display/msm/qcom,qcm2290-mdss.yaml | 34 +++++++++++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index dbc0613e427ed..a2f3e91104af3 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -33,6 +33,7 @@ properties: - qcom,sdm660-dsi-ctrl - qcom,sdm670-dsi-ctrl - qcom,sdm845-dsi-ctrl + - qcom,shikra-dsi-ctrl - qcom,sm6115-dsi-ctrl - qcom,sm6125-dsi-ctrl - qcom,sm6150-dsi-ctrl diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml index be6cd8adb3b67..cc1f227ade2d3 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml @@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml# properties: compatible: - const: qcom,qcm2290-dpu + enum: + - qcom,qcm2290-dpu + - qcom,shikra-dpu reg: items: diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml index bb09ecd1a5b4f..8271cb71bab8f 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml @@ -4,21 +4,35 @@ $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm QCM220 Display MDSS +title: Qualcomm QCM2290 and Shikra Display MDSS maintainers: - Loic Poulain + - Mahadevan P description: Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS - are mentioned for QCM2290 target. + are mentioned for QCM2290 and Shikra targets. Shikra uses the same MDSS/DPU/DSI + hardware as QCM2290 (DPU 6.5) and shares the same register layout. $ref: /schemas/display/msm/mdss-common.yaml# +select: + properties: + compatible: + contains: + enum: + - qcom,qcm2290-mdss + - qcom,shikra-mdss + required: + - compatible + properties: compatible: - const: qcom,qcm2290-mdss + enum: + - qcom,qcm2290-mdss + - qcom,shikra-mdss clocks: items: @@ -52,7 +66,9 @@ patternProperties: properties: compatible: - const: qcom,qcm2290-dpu + enum: + - qcom,qcm2290-dpu + - qcom,shikra-dpu "^dsi@[0-9a-f]+$": type: object @@ -60,9 +76,13 @@ patternProperties: properties: compatible: - items: - - const: qcom,qcm2290-dsi-ctrl - - const: qcom,mdss-dsi-ctrl + oneOf: + - items: + - const: qcom,qcm2290-dsi-ctrl + - const: qcom,mdss-dsi-ctrl + - items: + - const: qcom,shikra-dsi-ctrl + - const: qcom,mdss-dsi-ctrl "^phy@[0-9a-f]+$": type: object From 99eb8b4d473b93feacec83c53033b1f6475ab6ad Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Tue, 12 May 2026 16:57:57 +0530 Subject: [PATCH 0691/1058] dt-bindings: display: panel: Add DLC0697 DSI panel binding Add Device Tree binding documentation for the DLC DLC0697 1080x1920 video-mode MIPI DSI panel. Add a MAINTAINERS entry covering the binding and the panel driver. Signed-off-by: Arpit Saini Signed-off-by: Mahadevan P --- .../bindings/display/panel/dlc,dlc0697.yaml | 66 +++++++++++++++++++ MAINTAINERS | 7 ++ 2 files changed, 73 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml b/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml new file mode 100644 index 0000000000000..8ae72a8265e61 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/dlc,dlc0697.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DLC DLC0697 1080x1920 video-mode DSI panel + +maintainers: + - Arpit Saini + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: dlc,dlc0697 + + reg: + maxItems: 1 + description: DSI virtual channel + + reset-gpios: true + + enable-gpios: true + + vddio-supply: + description: I/O voltage supply (1.8V) + + bias-supply: + description: LCD bias supply (3.3V), typically a GPIO-controlled fixed regulator + + port: true + +required: + - compatible + - reg + - reset-gpios + - vddio-supply + - port + +additionalProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + vddio-supply = <&vreg_l15>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a99..846d74148fb0a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8024,6 +8024,13 @@ S: Maintained F: Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml F: drivers/gpu/drm/bridge/chipone-icn6211.c +DRM DRIVER FOR DLC DLC0697 DSI PANEL +M: Arpit Saini +S: Maintained +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml +F: drivers/gpu/drm/panel/panel-dlc0697.c + DRM DRIVER FOR EBBG FT8719 PANEL M: Joel Selvaraj S: Maintained From 36793fce5c17f8af20e0e02c64aaa583df2677ff Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Tue, 5 May 2026 19:57:34 +0530 Subject: [PATCH 0692/1058] drm/msm/mdss: Add Shikra support Add Mobile Display Subsystem (MDSS) support for the Shikra platform. Shikra uses the same MDSS and DPU 6.5 hardware as QCM2290, so it reuses the same AHB clock rate configuration (data_76k8) and DPU catalog. Register qcom,shikra-dpu in the DPU KMS match table pointing to dpu_qcm2290_cfg. Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_mdss.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index da3556eb6ecc2..8abe8ef6fa9ab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1496,6 +1496,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, }, { .compatible = "qcom,sdm845-dpu", .data = &dpu_sdm845_cfg, }, + { .compatible = "qcom,shikra-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sc7180-dpu", .data = &dpu_sc7180_cfg, }, { .compatible = "qcom,sc7280-dpu", .data = &dpu_sc7280_cfg, }, { .compatible = "qcom,sc8180x-dpu", .data = &dpu_sc8180x_cfg, }, diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 9087c4b290dba..03f27e6b0ae7b 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -537,6 +537,7 @@ static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,sar2130p-mdss", .data = &data_74k }, { .compatible = "qcom,sdm670-mdss", .data = &data_76k8 }, { .compatible = "qcom,sdm845-mdss", .data = &data_76k8 }, + { .compatible = "qcom,shikra-mdss", .data = &data_76k8 }, { .compatible = "qcom,sc7180-mdss", .data = &data_76k8 }, { .compatible = "qcom,sc7280-mdss", .data = &data_74k }, { .compatible = "qcom,sc8180x-mdss", .data = &data_76k8 }, From 8c706c367eb19a5b0f12937fa12d47bae19d310a Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Tue, 12 May 2026 17:01:53 +0530 Subject: [PATCH 0693/1058] drm/panel: Add driver for DLC0697 FHD video-mode DSI panel Add a DRM panel driver for the DLC0697 1080x1920@60Hz MIPI DSI panel. The driver implements the panel init/exit sequence, power and reset handling, a fixed display mode, and DCS backlight control. The panel operates in video burst mode with four data lanes using RGB888 pixel format. Backlight enable GPIO is toggled directly in enable/disable; backlight brightness is managed via the DRM backlight framework using the 16-bit DCS brightness API. Signed-off-by: Arpit Saini Signed-off-by: Mahadevan P --- drivers/gpu/drm/panel/Kconfig | 11 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-dlc0697.c | 339 ++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-dlc0697.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7450b27622a23..4354b51cbc53d 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -116,6 +116,17 @@ config DRM_PANEL_CHIPWEALTH_CH13726A Say Y here if you want to enable support for ChipWealth CH13726A-based display panels. +config DRM_PANEL_DLC0697 + tristate "DLC0697 1080x1920 video mode DSI panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the DLC DLC0697 + 1080x1920 60Hz MIPI-DSI video mode panel found on Qualcomm + Shikra (QCM2290-based) EVK boards. The panel supports hardware + backlight control via the MIPI DCS brightness command. + config DRM_PANEL_EBBG_FT8719 tristate "EBBG FT8719 panel driver" depends on GPIOLIB diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index c2c5cf8171163..3a8314b438361 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_LL2) += panel-boe-tv101wum-ll2.o obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o obj-$(CONFIG_DRM_PANEL_CHIPWEALTH_CH13726A) += panel-chipwealth-ch13726a.o obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o +obj-$(CONFIG_DRM_PANEL_DLC0697) += panel-dlc0697.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o obj-$(CONFIG_DRM_PANEL_EDP) += panel-edp.o diff --git a/drivers/gpu/drm/panel/panel-dlc0697.c b/drivers/gpu/drm/panel/panel-dlc0697.c new file mode 100644 index 0000000000000..f0ef07cb0160f --- /dev/null +++ b/drivers/gpu/drm/panel/panel-dlc0697.c @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +/* + * DRM panel driver for DLC0697 1080x1920 60Hz video-mode DSI panel + * + * Derived from downstream Qualcomm panel DT data. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct dlc0697 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + + struct pinctrl *pinctrl; + struct pinctrl_state *state_active; + struct pinctrl_state *state_suspend; +}; + +static const struct regulator_bulk_data dlc0697_supplies[] = { + { .supply = "vddio" }, + { .supply = "bias" }, +}; + +static inline struct dlc0697 *to_dlc0697(struct drm_panel *panel) +{ + return container_of(panel, struct dlc0697, panel); +} + +static const struct drm_display_mode dlc0697_mode = { + .clock = 131911, + + .hdisplay = 1080, + .hsync_start = 1080 + 18, + .hsync_end = 1080 + 18 + 2, + .htotal = 1080 + 18 + 2 + 16, + + .vdisplay = 1920, + .vsync_start = 1920 + 26, + .vsync_end = 1920 + 26 + 4, + .vtotal = 1920 + 26 + 4 + 20, + + .width_mm = 0, + .height_mm = 0, +}; + +static void dlc0697_reset(struct dlc0697 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); +} + +static int dlc0697_on(struct dlc0697 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_soft_reset_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x78, 0x07, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x09, 0x99); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x3f, 0xff); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + if (dsi_ctx.accum_err) + dev_err(&ctx->dsi->dev, "panel on sequence failed: %d\n", dsi_ctx.accum_err); + + return dsi_ctx.accum_err; +} + +static int dlc0697_off(struct dlc0697 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + if (dsi_ctx.accum_err) + dev_err(&ctx->dsi->dev, "panel off sequence failed: %d\n", dsi_ctx.accum_err); + + return dsi_ctx.accum_err; +} + +static int dlc0697_enable(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + if (ctx->enable_gpio) + gpiod_set_value_cansleep(ctx->enable_gpio, 1); + + return 0; +} + +static int dlc0697_disable(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + if (ctx->enable_gpio) + gpiod_set_value_cansleep(ctx->enable_gpio, 0); + + return 0; +} + +static int dlc0697_prepare(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + int ret; + + if (ctx->pinctrl && ctx->state_active) { + ret = pinctrl_select_state(ctx->pinctrl, ctx->state_active); + if (ret < 0) + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + if (ret < 0) { + dev_err(ctx->panel.dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + /* qcom,supply-post-on-sleep = <20> */ + msleep(20); + + dlc0697_reset(ctx); + + ret = dlc0697_on(ctx); + if (ret < 0) + goto err; + + return 0; + +err: + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + + if (ctx->pinctrl && ctx->state_suspend) + pinctrl_select_state(ctx->pinctrl, ctx->state_suspend); + + regulator_bulk_disable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + + return ret; +} + +static int dlc0697_unprepare(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + dlc0697_off(ctx); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + + if (ctx->pinctrl && ctx->state_suspend) + pinctrl_select_state(ctx->pinctrl, ctx->state_suspend); + + regulator_bulk_disable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + + return 0; +} + +static int dlc0697_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &dlc0697_mode); +} + +static const struct drm_panel_funcs dlc0697_panel_funcs = { + .prepare = dlc0697_prepare, + .unprepare = dlc0697_unprepare, + .enable = dlc0697_enable, + .disable = dlc0697_disable, + .get_modes = dlc0697_get_modes, +}; + +static int dlc0697_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + return 0; +} + +static const struct backlight_ops dlc0697_bl_ops = { + .update_status = dlc0697_bl_update_status, +}; + +static struct backlight_device *dlc0697_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 4095, + .max_brightness = 4095, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &dlc0697_bl_ops, &props); +} + +static int dlc0697_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct dlc0697 *ctx; + int ret; + + ctx = devm_drm_panel_alloc(dev, struct dlc0697, panel, + &dlc0697_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(dlc0697_supplies), + dlc0697_supplies, &ctx->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "failed to get reset gpio\n"); + + ctx->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(ctx->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), + "failed to get enable gpio\n"); + + ctx->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(ctx->pinctrl)) { + if (PTR_ERR(ctx->pinctrl) == -ENODEV) { + ctx->pinctrl = NULL; + } else { + return dev_err_probe(dev, PTR_ERR(ctx->pinctrl), + "failed to get pinctrl\n"); + } + } + + if (ctx->pinctrl) { + ctx->state_active = pinctrl_lookup_state(ctx->pinctrl, "default"); + if (IS_ERR(ctx->state_active)) + ctx->state_active = NULL; + + ctx->state_suspend = pinctrl_lookup_state(ctx->pinctrl, "sleep"); + if (IS_ERR(ctx->state_suspend)) + ctx->state_suspend = NULL; + } + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST; + + ctx->panel.prepare_prev_first = true; + + ctx->panel.backlight = dlc0697_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "failed to attach dsi\n"); + } + + return 0; +} + +static void dlc0697_remove(struct mipi_dsi_device *dsi) +{ + drm_panel_remove(mipi_dsi_get_drvdata(dsi)); +} + +static const struct of_device_id dlc0697_of_match[] = { + { .compatible = "dlc,dlc0697" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dlc0697_of_match); + +static struct mipi_dsi_driver dlc0697_driver = { + .probe = dlc0697_probe, + .remove = dlc0697_remove, + .driver = { + .name = "panel-dlc0697", + .of_match_table = dlc0697_of_match, + }, +}; +module_mipi_dsi_driver(dlc0697_driver); + +MODULE_AUTHOR("Arpit Saini "); +MODULE_DESCRIPTION("DLC0697 1080x1920 video mode DSI panel"); +MODULE_LICENSE("GPL"); From eb84a2bb91536f0e078a8546b0e0afc3f1f513ef Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Wed, 6 May 2026 10:17:26 +0530 Subject: [PATCH 0694/1058] arm64: defconfig: Enable DLC0697 DSI panel driver Enable the DLC0697 1080x1920 video-mode DSI panel driver as a module, used on the Shikra CQM EVK board. Signed-off-by: Mahadevan P --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 21f3a52f9f76e..344e3b3a5052e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1007,6 +1007,7 @@ CONFIG_DRM_MXSFB=m CONFIG_DRM_IMX_LCDIF=m CONFIG_DRM_NOUVEAU=m CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m +CONFIG_DRM_PANEL_DLC0697=m CONFIG_DRM_PANEL_LVDS=m CONFIG_DRM_PANEL_HIMAX_HX8279=m CONFIG_DRM_PANEL_HIMAX_HX83112A=m From 94a9d6adf2ea6b67480eb3fb92f2afbd0c9da98e Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 11 May 2026 15:58:52 +0530 Subject: [PATCH 0695/1058] soc: qcom: ubwc: Add Shikra UBWC config Add UBWC configuration for the Shikra platform. Shikra has no UBWC support and no highest_bank_bit setting, so use no_ubwc_data. Signed-off-by: Mahadevan P --- drivers/soc/qcom/ubwc_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 3fe47d8f0f638..01dca97e26714 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -278,6 +278,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,sdm660", .data = &msm8937_data }, { .compatible = "qcom,sdm670", .data = &sdm670_data, }, { .compatible = "qcom,sdm845", .data = &sdm845_data, }, + { .compatible = "qcom,shikra", .data = &no_ubwc_data, }, { .compatible = "qcom,sm4250", .data = &sm6115_data, }, { .compatible = "qcom,sm6115", .data = &sm6115_data, }, { .compatible = "qcom,sm6125", .data = &sm6125_data, }, From 674709ee277b764c605578c7f4859d32eb55c1c3 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 9 Apr 2026 14:52:06 +0530 Subject: [PATCH 0696/1058] ASoC: dt-bindings: Add schema for qcom,wsa885x-i2c Add a devicetree binding schema for Qualcomm WSA885X smart speaker amplifier on I2C. Document the device compatible, supplies, GPIOs, DAI cell count and initialization table property used by the driver. Keep a single init table property (wsa885x-init-table) as currently supported. Signed-off-by: Prasad Kumpatla --- .../bindings/sound/qcom,wsa885x-i2c.yaml | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml new file mode 100644 index 0000000000000..6bc742b0aacf8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,wsa885x-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm WSA885X I2C smart speaker amplifier + +maintainers: + - Srinivas Kandagatla + +allOf: + - $ref: dai-common.yaml# + +description: | + WSA885X is a Qualcomm smart speaker amplifier codec. + This binding describes the I2C control interface and + board-level resources required by the codec. + +properties: + compatible: + const: qcom,wsa885x-i2c + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + powerdown-gpios: + description: GPIO spec for the codec shutdown/powerdown pin. + maxItems: 1 + + interrupt-gpios: + description: GPIO spec for the codec interrupt pin. + maxItems: 1 + + vdd-io-supply: + description: 1.8V I/O supply. + + vdd-1p8-supply: + description: 1.8V analog/digital core supply. + + qcom,battery_config: + description: Battery topology configuration. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2] + + wsa885x-init-table: + description: Register/value initialization table as pairs. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 512 + +required: + - compatible + - reg + - '#sound-dai-cells' + - vdd-io-supply + - vdd-1p8-supply + - wsa885x-init-table + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + speaker-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + #sound-dai-cells = <0>; + + qcom,battery_config = <1>; + + powerdown-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + interrupt-gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; + + vdd-io-supply = <&vreg_l15a_1p8>; + vdd-1p8-supply = <&vreg_l10a_1p8>; + + wsa885x-init-table = < + 0x800d 0x1c + 0x8090 0x1f + >; + }; + }; + +... From a8405bfc3a07d98e9a33894e228ad1038caf31a7 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 9 Apr 2026 16:22:47 +0530 Subject: [PATCH 0697/1058] ASoC: codecs: add Qualcomm WSA885X I2C codec driver Add a new ASoC codec driver for Qualcomm WSA885X over I2C. Signed-off-by: Prasad Kumpatla --- sound/soc/codecs/Kconfig | 9 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wsa885x-i2c.c | 1359 ++++++++++++++++++++++++++++++++ 3 files changed, 1370 insertions(+) create mode 100644 sound/soc/codecs/wsa885x-i2c.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 252f683be3c18..9ceb474a18de9 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -367,6 +367,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_WSA881X imply SND_SOC_WSA883X imply SND_SOC_WSA884X + imply SND_SOC_WSA885X_I2C imply SND_SOC_ZL38060 help Normally ASoC codec drivers are only built if a machine driver which @@ -2770,6 +2771,14 @@ config SND_SOC_WSA884X This enables support for Qualcomm WSA8840/WSA8845/WSA8845H Class-D Smart Speaker Amplifier. +config SND_SOC_WSA885X_I2C + tristate "WSA885X I2C Codec" + depends on I2C + select REGMAP_I2C + help + This enables support for Qualcomm WSA885X Smart Speaker + Amplifier over I2C. + config SND_SOC_ZL38060 tristate "Microsemi ZL38060 Connected Home Audio Processor" depends on SPI_MASTER diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index aa0396e5b575b..18cfff959290c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -426,6 +426,7 @@ snd-soc-wm-hubs-y := wm_hubs.o snd-soc-wsa881x-y := wsa881x.o snd-soc-wsa883x-y := wsa883x.o snd-soc-wsa884x-y := wsa884x.o +snd-soc-wsa885x-i2c-y := wsa885x-i2c.o snd-soc-zl38060-y := zl38060.o # Amp snd-soc-max9877-y := max9877.o @@ -876,6 +877,7 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o obj-$(CONFIG_SND_SOC_WSA883X) += snd-soc-wsa883x.o obj-$(CONFIG_SND_SOC_WSA884X) += snd-soc-wsa884x.o +obj-$(CONFIG_SND_SOC_WSA885X_I2C) += snd-soc-wsa885x-i2c.o obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o # Amp diff --git a/sound/soc/codecs/wsa885x-i2c.c b/sound/soc/codecs/wsa885x-i2c.c new file mode 100644 index 0000000000000..2ace3a0956b25 --- /dev/null +++ b/sound/soc/codecs/wsa885x-i2c.c @@ -0,0 +1,1359 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* WSA885X I2C codec driver */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Driver Constants */ +#define CLK_RATE_FIXED 73728000 +#define SUPPLIES_NUM 2 +#define SLAVE_ADDR 0x00c +#define NUM_REGS 0x03 + +/* Interrupt Registers */ +#define WSA885X_INTR_STATUS0 0x8584 /* Base address of the status register */ +#define WSA885X_INTR_MASK0 0x8581 /* Base address of the mask register */ +#define WSA885X_INTR_CLEAR0 0x8587 /* Base address of the acknowledge register */ +#define WSA885X_INTR_LEVEL0 0x858A /* Base address of the acknowledge register */ + +/* Power and PA FSM Control Registers */ +#define WSA885X_POWER_FSM_CTL0 0x8423 +#define WSA885X_PA0_FSM_CTL0 0x842A +#define WSA885X_PA1_FSM_CTL0 0x8434 + +/* Digital Control GPIO and Interrupt Registers */ +#define DIG_CTRL1_PIN_CT 0x8510 +#define DIG_CTRL1_SPMI_PAD_GPIO2_CTL 0x8518 +#define DIG_CTRL1_INTR_MODE 0x8580 + +/* Control Registers - Audio Processing */ +#define SMP_AMP_CTRL_STEREO_STEREO_SMP_AMP_CTRL_I2S 0x0000 +#define SMP_AMP_CTRL_STEREO_CMT_GRP_MASK 0x0004 +#define SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX 0x0140 +#define SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID 0x0208 +#define SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX 0x0240 +#define SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER 0x0340 +#define SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0 0x4405 +#define SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1 0x4406 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB 0x4409 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB 0x6409 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB 0x440a +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB 0x640a +#define SMP_AMP_CTRL_STEREO_PDE23_REQ_PS 0x0a04 +#define SMP_AMP_CTRL_STEREO_PDE23_ACT_PS 0x0a40 +#define SMP_AMP_CTRL_STEREO_OT23_USAGE 0x0b10 +#define SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX 0x0e40 + +/* Analog Top Registers - Power and Clock Control */ +#define ANA_TOP_PON_CKSK_CTL_0 0x800d +#define ANA_TOP_BG_TVP_UVLO1_PROG 0x8024 +#define ANA_TOP_BG_TVP_UVLO2_PROG 0x8025 +#define ANA_TOP_BG_TVP_OVRD_CTL 0x8034 + +/* Analog PLL Registers */ +#define ANA_PLL_DIV_CTL_0 0x8090 +#define ANA_PLL_DIV_CTL_1 0x8091 +#define ANA_TOP_PLL_VCO_CTL 0x8092 +#define ANA_TOP_PLL_LOOPFILT_0 0x8093 +#define ANA_TOP_PLL_OVRD_CTL 0x8098 +#define ANA_TOP_PLL_STATUS_0 0x809a +#define ANA_TOP_PLL_STATUS_1 0x809b + +/* Analog Boost Control Registers */ +#define ANA_TOP_BOOST_STB_CTRL2 0x805b +#define ANA_TOP_BOOST_STB_CTRL3 0x805c +#define ANA_TOP_BOOST_BYP_CTRL2 0x805e +#define ANA_TOP_BOOST_BYP_CTRL3 0x805f +#define ANA_TOP_BOOST_MISC 0x8063 +#define ANA_TOP_BOOST_PWRSTAGE_CTRL2 0x8065 +#define ANA_TOP_BOOST_PWRSTAGE_CTRL4 0x8067 + +/* Analog IV Sense ADC Registers */ +#define ANA_TOP_IVSENSE_ADC_MODE_CTL2 0x80ca +#define ANA_TOP_IVSENSE_ADC_MODE_CTL3 0x80cb +#define ANA_TOP_IVSENSE_ADC_REF_CTL 0x80cc +#define ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 0x80d0 + +/* Analog Speaker Power Stage Registers */ +#define ANA_TOP_SPK_TOP_PWRSTG_CH1_CTRL3 0x8108 +#define ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 0x810b +#define ANA_TOP_SPK_TOP_PWRSTG_CH2_CTRL3 0x810e +#define ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 0x8111 +#define ANA_TOP_SPK_TOP_SPARE3 0x813c +#define SPK_TOP_LF_CH1_CTRL11 0x811c +#define SPK_TOP_LF_CH1_TUNE1 0x811d +#define SPK_TOP_LF_CH2_TUNE1 0x8129 +#define SPK_TOP_LF_CH1_CTRL9 0x811a +#define SPK_TOP_LF_CH2_CTRL9 0x8126 +#define SPK_TOP_LF_CH2_CTRL11 0x8128 +#define SPK_TOP_COMMON_CTRL2 0x8102 +#define SPK_TOP_COMMON_TUNE1 0x8103 +#define IVSENSE_VSNS_ISNS_CTL_CH1 0x80ba +#define DIG_CTRL0_CDC_CLK_CTL 0x841c +#define PON_CKSK_CTL_0 0x800d +#define DIG_CTRL0_TOP_CLK_CFG 0x8418 +#define DIG_CTRL0_SDCA_COMMIT 0x8419 +#define DIG_CTRL0_CLK_SOURCE_ENABLE 0x841a +#define DIG_CTRL0_SYS_CLK_SEL 0x841b +#define DIG_CTRL0_CDC_CLK_CTL 0x841c +#define DIG_CTRL0_PA_FSM_CTL 0x8420 +#define DIG_CTRL0_POWER_FSM_CTL0 0x8423 +#define DIG_CTRL0_POWER_FSM_CTL1 0x8424 +#define DIG_CTRL0_PA0_FSM_CTL1 0x842b +#define DIG_CTRL0_PA1_FSM_CTL1 0x8435 +#define DIG_CTRL0_VBAT_THRM_FLT_CTL 0x8458 +#define DIG_CTRL0_CDC_RXTX_FSCNT_CTL 0x8470 +#define DIG_CTRL0_GAIN_RAMP0_CTL1 0x84b4 +#define DIG_CTRL0_GAIN_RAMP1_CTL1 0x84b7 + +/* Digital Control 1 Registers - I2S/TDM Interface */ +#define DIG_CTRL1_I2S_CTL0 0x85A0 +#define DIG_CTRL1_I2S_CFG0_TDM_TX 0x85A2 +#define DIG_CTRL1_I2S_CFG1_TDM_TX 0x85A3 +#define DIG_CTRL1_I2S_TDM_CTL0 0x85A7 +#define DIG_CTRL1_I2S_TDM_CTL1 0x85A9 +#define DIG_CTRL1_I2S_TDM_CH_RX 0x85AA +#define DIG_CTRL1_I2S_TDM_CH_TX 0x85AB +#define DIG_CTRL1_I2S_RESET_CTL 0x85AE + +/* CDC RX Path Registers - Audio Data Path */ +#define CDC_RX0_RX_PATH_CFG0 0x8601 +#define CDC_RX0_RX_PATH_CFG1 0x8602 +#define CDC_RX0_RX_PATH_CTL 0x8606 +#define RX0_RX_PATH_DSMDEM_CTL 0x8613 +#define CDC_RX1_RX_PATH_CFG0 0x8621 +#define CDC_RX1_RX_PATH_CFG1 0x8622 +#define CDC_RX1_RX_PATH_CTL 0x8626 +#define RX1_RX_PATH_DSMDEM_CTL 0x8633 + +/* CDC Compander Registers - Dynamic Range Control */ +#define CDC_COMPANDER0_CTL0 0x8640 +#define CDC_COMPANDER0_CTL7 0x8647 +#define CDC_COMPANDER1_CTL0 0x8660 +#define CDC_COMPANDER1_CTL7 0x8667 + +/* CDC Speaker Protection Registers - IV Sense */ +#define CDC_VSENSE0_SPKR_PROT_PATH_CTL 0x86A1 +#define CDC_VSENSE1_SPKR_PROT_PATH_CTL 0x86B1 +#define CDC_ISENSE0_SPKR_PROT_PATH_CTL 0x86A9 +#define CDC_ISENSE1_SPKR_PROT_PATH_CTL 0x86B9 + +/* CDC Class-H Registers - Headroom Control */ +#define CDC_CLSH_V1P8_BP_CTL1 0x86CD +#define CDC_CLSH_V1P8_BP_CTL0 0x86CC +#define CDC_CLSH_CLSH_SIG_DP_CTL0 0x86C7 +#define CDC_CLSH_CLSH_V_HD_PA 0x86C3 +#define CDC_CLSH_V1P8_BP_CTL2 0x86CE + +/* RX Sample Rate Index Values - Audio Playback Path */ +#define WSA885X_RX_RATE_8000HZ 0x00 /* 8 kHz sample rate */ +#define WSA885X_RX_RATE_16000HZ 0x01 /* 16 kHz sample rate */ +#define WSA885X_RX_RATE_32000HZ 0x02 /* 32 kHz sample rate */ +#define WSA885X_RX_RATE_44100HZ 0x03 /* 44.1 kHz sample rate */ +#define WSA885X_RX_RATE_48000HZ 0x04 /* 48 kHz sample rate */ +#define WSA885X_RX_RATE_96000HZ 0x05 /* 96 kHz sample rate */ +#define WSA885X_RX_RATE_192000HZ 0x06 /* 192 kHz sample rate */ +#define WSA885X_RX_RATE_384000HZ 0x07 /* 384 kHz sample rate */ + +/* VI Sample Rate Index Values - Voltage/Current Sensing Path */ +#define WSA885X_VI_RATE_8000HZ 0x00 /* 8 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_16000HZ 0x01 /* 16 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_44100HZ 0x02 /* 44.1 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_48000HZ 0x03 /* 48 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_96000HZ 0x04 /* 96 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_22050HZ 0x05 /* 22.05 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_24000HZ 0x06 /* 24 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_192000HZ 0x07 /* 192 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_384000HZ 0x08 /* 384 kHz sample rate for VI sensing */ + +/* Channel Configuration Masks */ +#define WSA885X_CHANNEL_STEREO 0x03 /* Both left and right channels (0b11) */ +#define WSA885X_CHANNEL_MONO_LEFT 0x01 /* Left channel only (0b01) */ +#define WSA885X_CHANNEL_MONO_RIGHT 0x02 /* Right channel only (0b10) */ + +/* PLL Status Register Bits */ +#define WSA885X_PLL_LOCK_BIT 0x01 /* PLL lock status bit (bit 0) */ + +/* FU21 volume support */ +#define FU21_VOL_STEPS 124 +static const DECLARE_TLV_DB_SCALE(fu21_digital_gain, -8400, 100, 0); + +static const char *const supply_name[] = { + "vdd-io", + "vdd-1p8", +}; + +enum { + batt_1s = 1, + batt_2s, +}; + +enum { + WSA885X_IRQ_INT_SAF2WAR = 0, + WSA885X_IRQ_INT_WAR2SAF, + WSA885X_IRQ_INT_DISABLE, + WSA885X_IRQ_INT_PA0_OCP, + WSA885X_IRQ_INT_PA1_OCP, + WSA885X_IRQ_INT_CLIP0, + WSA885X_IRQ_INT_CLIP1, + WSA885X_IRQ_INT_CLK_WD, + WSA885X_IRQ_INT_INTR_GPIO1_PIN, + WSA885X_IRQ_INT_INTR_GPIO2_PIN, + WSA885X_IRQ_INT_UVLO, + WSA885X_IRQ_INT_BOP, + WSA885X_IRQ_INT_PA0_FSM_ERR, + WSA885X_IRQ_INT_PA1_FSM_ERR, + WSA885X_IRQ_INT_MAIN_FSM_ERR, + WSA885X_IRQ_INT_PCM_DATA0_WD, + WSA885X_IRQ_INT_PCM_DATA1_WD, + WSA885X_IRQ_INT_PCM_DATA0_DC, + WSA885X_IRQ_INT_PCM_DATA1_DC, + WSA885X_IRQ_INT_PLL_UNLOCKED, + WSA885X_IRQ_INT_PROT_MODE_CHANGE, + WSA885X_IRQ_INT_PB_CLOCK_VALID, + WSA885X_IRQ_INT_SENSE_CLOCK_VALID, + WSA885X_IRQ_MAX, +}; + +static const char *wsa885x_irq_names[WSA885X_IRQ_MAX] = { + "WSA885X_IRQ_INT_SAF2WAR", + "WSA885X_IRQ_INT_WAR2SAF", + "WSA885X_IRQ_INT_DISABLE", + "WSA885X_IRQ_INT_PA0_OCP", + "WSA885X_IRQ_INT_PA1_OCP", + "WSA885X_IRQ_INT_CLIP0", + "WSA885X_IRQ_INT_CLIP1", + "WSA885X_IRQ_INT_CLK_WD", + "WSA885X_IRQ_INT_INTR_GPIO1_PIN", + "WSA885X_IRQ_INT_INTR_GPIO2_PIN", + "WSA885X_IRQ_INT_UVLO", + "WSA885X_IRQ_INT_BOP", + "WSA885X_IRQ_INT_PA0_FSM_ERR", + "WSA885X_IRQ_INT_PA1_FSM_ERR", + "WSA885X_IRQ_INT_MAIN_FSM_ERR", + "WSA885X_IRQ_INT_PCM_DATA0_WD", + "WSA885X_IRQ_INT_PCM_DATA1_WD", + "WSA885X_IRQ_INT_PCM_DATA0_DC", + "WSA885X_IRQ_INT_PCM_DATA1_DC", + "WSA885X_IRQ_INT_PLL_UNLOCKED", + "WSA885X_IRQ_INT_PROT_MODE_CHANGE", + "WSA885X_IRQ_INT_PB_CLOCK_VALID", + "WSA885X_IRQ_INT_SENSE_CLOCK_VALID"}; + +struct wsa885x_i2c_priv { + struct i2c_client *client; + struct regmap *regmap; + struct device *dev; + struct snd_soc_component *component; + struct regulator_bulk_data supplies[SUPPLIES_NUM]; + struct gpio_desc *sd_n; + uint32_t sample_rate; + uint32_t *init_table; + uint32_t init_table_size; + uint32_t usage_mode; + uint32_t rx_slot_mask; + struct gpio_desc *intr_pin; + atomic_t open_count; + uint32_t batt_conf; + int stereo_voldB; /* in dB, -84..+40, encoded as signed 8-bit in MSB register */ +}; + +static const struct regmap_range_cfg regmap_ranges[] = { + { + .range_min = 0, + .range_max = 0x88ff, + .selector_reg = 0x0, + .selector_mask = 0xFF, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct reg_default codec_reg_defaults[] = { + {SMP_AMP_CTRL_STEREO_STEREO_SMP_AMP_CTRL_I2S, 0x00}, + {SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01}, + {SMP_AMP_CTRL_STEREO_CMT_GRP_MASK, 0x00}, + {SMP_AMP_CTRL_STEREO_OT23_USAGE, 0x00}, + {SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID, 0x00}, + {SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX, 0x04}, + {SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, 0xac}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, 0xac}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00}, + {SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x03}, + {SMP_AMP_CTRL_STEREO_PDE23_ACT_PS, 0x03}, + {SMP_AMP_CTRL_STEREO_OT23_USAGE, 0x00}, + {SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, 0x03}, + {SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, 0x03}, + {ANA_TOP_PON_CKSK_CTL_0, 0x00}, + {ANA_TOP_BG_TVP_UVLO1_PROG, 0x19}, + {ANA_TOP_BG_TVP_UVLO2_PROG, 0x22}, + {ANA_PLL_DIV_CTL_0, 0x0c}, + {ANA_PLL_DIV_CTL_1, 0x50}, + {ANA_TOP_PLL_VCO_CTL, 0x00}, + {ANA_TOP_PLL_LOOPFILT_0, 0xb4}, + {ANA_TOP_PLL_OVRD_CTL, 0x00}, + {ANA_TOP_BG_TVP_OVRD_CTL, 0x00}, + {ANA_TOP_BOOST_STB_CTRL2, 0x03}, + {ANA_TOP_BOOST_STB_CTRL3, 0x3c}, + {ANA_TOP_BOOST_BYP_CTRL2, 0xc5}, + {ANA_TOP_BOOST_BYP_CTRL3, 0x13}, + {ANA_TOP_BOOST_MISC, 0x79}, + {ANA_TOP_SPK_TOP_SPARE3, 0x00}, + {SPK_TOP_COMMON_CTRL2, 0x08}, + {SPK_TOP_LF_CH1_CTRL11, 0x09}, + {SPK_TOP_LF_CH1_TUNE1, 0x00}, + {SPK_TOP_LF_CH2_TUNE1, 0x00}, + {SPK_TOP_LF_CH1_CTRL9, 0x00}, + {SPK_TOP_LF_CH2_CTRL9, 0x00}, + {SPK_TOP_LF_CH2_CTRL11, 0x09}, + {SPK_TOP_COMMON_TUNE1, 0x08}, + {SPK_TOP_COMMON_TUNE1, 0x03}, + {IVSENSE_VSNS_ISNS_CTL_CH1, 0x00}, + {DIG_CTRL0_CDC_CLK_CTL, 0x0e}, + {PON_CKSK_CTL_0, 0x00}, + {ANA_TOP_BOOST_PWRSTAGE_CTRL2, 0x40}, + {ANA_TOP_BOOST_PWRSTAGE_CTRL4, 0xff}, + {ANA_TOP_PLL_STATUS_0, 0x00}, + {ANA_TOP_PLL_STATUS_1, 0x00}, + {ANA_TOP_IVSENSE_ADC_MODE_CTL2, 0x84}, + {ANA_TOP_IVSENSE_ADC_MODE_CTL3, 0x02}, + {ANA_TOP_IVSENSE_ADC_REF_CTL, 0x00}, + {ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2, 0xe0}, + {ANA_TOP_SPK_TOP_PWRSTG_CH1_CTRL3, 0xa4}, + {ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3, 0xc9}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_CTRL3, 0xa4}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3, 0xc5}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3, 0xc9}, + {DIG_CTRL0_TOP_CLK_CFG, 0x00}, + {DIG_CTRL0_SDCA_COMMIT, 0x00}, + {DIG_CTRL0_CLK_SOURCE_ENABLE, 0x00}, + {DIG_CTRL0_SYS_CLK_SEL, 0x00}, + {DIG_CTRL0_CDC_CLK_CTL, 0x0e}, + {DIG_CTRL0_PA_FSM_CTL, 0x00}, + {DIG_CTRL0_POWER_FSM_CTL0, 0x05}, + {DIG_CTRL0_POWER_FSM_CTL1, 0x00}, + {DIG_CTRL0_PA0_FSM_CTL1, 0x45}, + {DIG_CTRL0_PA1_FSM_CTL1, 0x45}, + {DIG_CTRL0_VBAT_THRM_FLT_CTL, 0x7f}, + {DIG_CTRL0_CDC_RXTX_FSCNT_CTL, 0x00}, + {DIG_CTRL0_GAIN_RAMP0_CTL1, 0x01}, + {DIG_CTRL0_GAIN_RAMP1_CTL1, 0x01}, + {DIG_CTRL1_I2S_CTL0, 0x06}, + {DIG_CTRL1_I2S_CFG0_TDM_TX, 0x00}, + {DIG_CTRL1_I2S_CFG1_TDM_TX, 0x00}, + {DIG_CTRL1_I2S_TDM_CTL0, 0x00}, + {DIG_CTRL1_I2S_TDM_CTL1, 0x05}, + {DIG_CTRL1_I2S_TDM_CH_TX, 0x00}, + {DIG_CTRL1_I2S_RESET_CTL, 0x00}, + {DIG_CTRL1_I2S_TDM_CH_RX, 0x08}, + {CDC_RX0_RX_PATH_CFG0, 0x89}, + {CDC_RX0_RX_PATH_CFG1, 0x64}, + {CDC_RX0_RX_PATH_CTL, 0x24}, + {RX0_RX_PATH_DSMDEM_CTL, 0x01}, + {CDC_RX1_RX_PATH_CFG0, 0x89}, + {CDC_RX1_RX_PATH_CFG1, 0x64}, + {CDC_RX1_RX_PATH_CTL, 0x04}, + {RX1_RX_PATH_DSMDEM_CTL, 0x01}, + {CDC_COMPANDER0_CTL0, 0x01}, + {CDC_COMPANDER0_CTL7, 0x2a}, + {CDC_COMPANDER1_CTL0, 0x01}, + {CDC_COMPANDER1_CTL7, 0x2a}, + {CDC_VSENSE0_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_VSENSE1_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_ISENSE0_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_ISENSE1_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_CLSH_V1P8_BP_CTL1, 0x50}, + {CDC_CLSH_V1P8_BP_CTL0, 0x6c}, + {CDC_CLSH_CLSH_SIG_DP_CTL0, 0x0d}, + {CDC_CLSH_CLSH_V_HD_PA, 0x03}, + {CDC_CLSH_V1P8_BP_CTL2, 0x05}, +}; + +static int wsa885x_gpio_set(struct wsa885x_i2c_priv *wsa885x, bool val) +{ + int ret = 0; + + if (val) + ret = gpiod_direction_output(wsa885x->sd_n, 1); + else + ret = gpiod_direction_output(wsa885x->sd_n, 0); + + if (ret < 0) { + dev_err_ratelimited(wsa885x->dev, "%s: failed to set GPIO: %d\n", __func__, + ret); + } + return ret; +} + +static void reg_update_sequence(struct regmap *regmap) +{ + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x15); + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x11); + + /* Configure TDM control register 0 */ + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x04); + regmap_update_bits(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x01, 0x01); + + /* Configure TDM transmit channel settings */ + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x01); + regmap_update_bits(regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x02, 0x02); +} + +static int wait_for_pll_lock(struct wsa885x_i2c_priv *wsa885x) +{ + unsigned int status; + int cnt = 0; + int ret = 0; + + do { + usleep_range(1000, 1100); + ret = regmap_read(wsa885x->regmap, ANA_TOP_PLL_STATUS_0, &status); + + /* Check if PLL is locked (bit 0 set) */ + if (ret == 0 && (status & WSA885X_PLL_LOCK_BIT)) { + dev_dbg(wsa885x->component->dev, "PLL locked successfully after %d ms\n", + cnt + 1); + return 0; + } + } while (++cnt < 20); /* Maximum 20ms timeout */ + + /* PLL lock timeout */ + dev_warn(wsa885x->component->dev, "PLL lock timeout after 20ms, status=0x%x\n", status); + return -ETIMEDOUT; +} + +static void wsa885x_2s_conf(struct wsa885x_i2c_priv *wsa885x) +{ + regmap_write(wsa885x->regmap, SPK_TOP_COMMON_TUNE1, 0x03); + regmap_write(wsa885x->regmap, SPK_TOP_LF_CH1_CTRL11, 0x0d); + regmap_write(wsa885x->regmap, SPK_TOP_LF_CH2_CTRL11, 0x0d); + regmap_write(wsa885x->regmap, CDC_CLSH_V1P8_BP_CTL1, 0x71); + regmap_write(wsa885x->regmap, CDC_CLSH_V1P8_BP_CTL0, 0xAA); +} + +static int wait_for_pde_state(struct wsa885x_i2c_priv *wsa885x, + int ps, int reg) +{ + int act_ps, cnt = 0, clock_valid; + int rc = 0; + + /* Poll for power state transition with timeout */ + do { + usleep_range(1000, 1500); + + /* Read actual power state from PDE register */ + rc = regmap_read(wsa885x->regmap, + SMP_AMP_CTRL_STEREO_PDE23_ACT_PS, + &act_ps); + + /* Check if desired power state is reached */ + if (rc == 0 && act_ps == ps) + return 0; + } while (++cnt < 5); + + /* Read clock validity status for debugging */ + regmap_read(wsa885x->regmap, + SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID, + &clock_valid); + + dev_err(wsa885x->component->dev, + "PDE power state %d request failed, actual_ps %d, clock_valid:%d\n", + ps, act_ps, clock_valid); + + return -ETIMEDOUT; +} + +static int codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = snd_soc_component_get_drvdata(component); + uint8_t value, cs21_sample_rate_idx, cs24_sample_rate_idx; + int open_count = 0; + + dev_dbg(wsa885x->dev, "%s: HW Params called with sampling rate as %d\n", __func__, + params_rate(params)); + + /* Check if multiple streams are open - only configure on first stream */ + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + + /* Extract sample rate from ALSA parameters */ + wsa885x->sample_rate = params_rate(params); + + /* Map sample rate to codec-specific rate indices */ + switch (wsa885x->sample_rate) { + case 8000: + value = 0x00; + cs21_sample_rate_idx = WSA885X_RX_RATE_8000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_8000HZ; + break; + case 16000: + value = 0x01; + cs21_sample_rate_idx = WSA885X_RX_RATE_16000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_16000HZ; + break; + case 32000: + value = 0x02; + cs21_sample_rate_idx = WSA885X_RX_RATE_32000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_48000HZ; + break; + case 44100: + value = 0x03; + cs21_sample_rate_idx = WSA885X_RX_RATE_44100HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_44100HZ; + break; + case 48000: + value = 0x03; + cs21_sample_rate_idx = WSA885X_RX_RATE_48000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_48000HZ; + break; + case 88200: + case 96000: + value = 0x04; + cs21_sample_rate_idx = WSA885X_RX_RATE_96000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_96000HZ; + break; + case 176400: + case 192000: + value = 0x05; + cs21_sample_rate_idx = WSA885X_RX_RATE_192000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_192000HZ; + break; + case 352800: + case 384000: + value = 0x06; + cs21_sample_rate_idx = WSA885X_RX_RATE_384000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_384000HZ; + break; + default: + dev_err(component->dev, "sampling rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* Configure I2S control register with sample rate (bits 1:4) and enable bit */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x1f, + (value << 1) + 1); + + /* Reset I2S interface */ + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x00); + + /* Set RX (playback) sample rate index */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX, + cs21_sample_rate_idx); + + /* Set VI (voltage/current sensing) sample rate index */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, + cs24_sample_rate_idx); + + /* Program FU21 volume with current dB value (MSB) and zero LSB, then commit */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + + return 0; +} + +static int codec_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_slot_mask, + unsigned int rx_slot_mask, int slots, + int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + dev_dbg(wsa885x->dev, "%s: TDM num_slots configured as %d\n", __func__, slots); + + /* Increment open count atomically - only configure on first call */ + if (atomic_inc_return(&wsa885x->open_count) > 1) + return 0; + + /* Reset I2S interface before configuration */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x01, 0x01); + + /* Configure TDM slots based on channel mask */ + if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_STEREO) { + /* Stereo configuration - both channels active */ + /* Configure slot0 for I-sense channel 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x01, 0x01); + /* Configure slot1 for I-sense channel 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x20, 0x20); + /* Configure slot3 for current protection sense 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, + 0x05, 0x05); + /* Configure slot4 for current protection sense 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, + 0x60, 0x60); + /* Apply TDM control sequence */ + reg_update_sequence(wsa885x->regmap); + /* Enable transmit channels */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, + 0x08, 0x08); + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_LEFT) { + /* Mono left channel configuration */ + /* Configure slot0 for I-sense channel 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x01, 0x01); + /* Configure slot1 for current protection sense 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x50, 0x50); + reg_update_sequence(wsa885x->regmap); + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_RIGHT) { + /* Mono right channel configuration */ + /* Configure slot0 for I-sense channel 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x02, 0x02); + /* Configure slot1 for current protection sense 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x60, 0x60); + reg_update_sequence(wsa885x->regmap); + } + + /* Enable I2S control */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x01, 0x01); + + /* Release I2S reset */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x01, 0x00); + + return 0; +} + +static int codec_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + uint8_t pll_div; + int i, open_count = 0, ret = 0; + + dev_dbg(wsa885x->dev, "%s: Freq: %d\n", __func__, freq); + + /* Check if multiple streams are open - only configure on first stream */ + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + + /* Calculate PLL divider: Fixed rate / target frequency */ + pll_div = CLK_RATE_FIXED / freq; + + /* Configure analog bias and thermal/voltage protection override */ + regmap_write(wsa885x->regmap, ANA_TOP_BG_TVP_OVRD_CTL, 0x03); + + /* Select internal system clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SYS_CLK_SEL, 0x04); + + /* Configure PLL loop filter for stability */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_LOOPFILT_0, 0xB4); + + /* Configure VCO (Voltage Controlled Oscillator) */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_VCO_CTL, 0x00); + + /* Disable PLL override mode */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_OVRD_CTL, 0x00); + + /* Set calculated PLL divider */ + regmap_write(wsa885x->regmap, ANA_PLL_DIV_CTL_0, pll_div); + + /* Enable PLL clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_CLK_SOURCE_ENABLE, 0x02); + + /* Wait for PLL to lock with intelligent polling */ + ret = wait_for_pll_lock(wsa885x); + if (ret) { + dev_err(wsa885x->component->dev, "PLL lock failed, aborting sysclk configuration\n"); + return ret; + } + + /* Switch to PLL as system clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SYS_CLK_SEL, 0x00); + + /* Enable power FSM control */ + regmap_write(wsa885x->regmap, DIG_CTRL0_POWER_FSM_CTL1, 0x01); + + /* Apply codec-specific initialization table from device tree */ + for (i = 0; i < wsa885x->init_table_size / 2; i++) { + if (wsa885x->batt_conf == batt_2s && wsa885x->init_table[2 * i] == + SPK_TOP_LF_CH1_CTRL11) + wsa885x_2s_conf(wsa885x); + else if (wsa885x->batt_conf == batt_2s && + wsa885x->init_table[2 * i] == SPK_TOP_COMMON_TUNE1) + regmap_write(wsa885x->regmap, SPK_TOP_COMMON_TUNE1, 0x26); + else + regmap_write(wsa885x->regmap, wsa885x->init_table[2 * i], + wsa885x->init_table[2 * i + 1]); + } + return 0; +} + +static int codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct wsa885x_i2c_priv *wsa885x = snd_soc_dai_get_drvdata(dai); + int ret = 0, ps0 = 0, ps3 = 3, open_count = 0; + + dev_dbg(wsa885x->dev, "%s: Stream is %s\n", __func__, mute ? "muted" : "unmuted"); + + if (mute) { + open_count = atomic_dec_return(&wsa885x->open_count); + if (open_count > 0) + return 0; + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + /* Request power state 3 (low power/standby mode) */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x03); + ret = wait_for_pde_state(wsa885x, ps3, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps3); + } + } else { + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + /* Disable power amplifier FSM before configuration */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + + /* Configure usage mode for thermal/speaker protection */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_OT23_USAGE, + wsa885x->usage_mode); + + /* Set cluster index for audio processing */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01); + + /* Set posture number for speaker configuration */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01); + + /* Apply requested volume */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + + /* Request power state 0 (active mode) */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x00); + ret = wait_for_pde_state(wsa885x, ps0, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps0); + } else { + dev_err(wsa885x->component->dev, "PS0 request failed\n"); + goto exit; + } + + /* Configure power amplifier based on channel configuration */ + if (wsa885x->rx_slot_mask == 0b11) { + /* Stereo mode - enable both PA channels */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x03); + } else if (wsa885x->rx_slot_mask == 0b01) { + /* Mono left channel */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x01); + } else if (wsa885x->rx_slot_mask == 0b10) { + /* Mono right channel */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0b10); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_RX, 0b01); + } + + /* Unmute both channels */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1, 0x00); + + /* Commit all changes */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + } +exit: + return ret; +} + +static int codec_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + int open_count = 0; + + dev_dbg(wsa885x->dev, "%s: HW Free, resetting I2S registers\n", __func__); + + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 0) + return 0; + + /* Reset I2S register in any case */ + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x05); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x06); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_RX, 0x08); + + /* Reset Clock */ + regmap_write(wsa885x->regmap, DIG_CTRL0_CLK_SOURCE_ENABLE, 0x00); + regmap_write(wsa885x->regmap, ANA_TOP_BG_TVP_OVRD_CTL, 0x00); + + return 0; +} + +static const struct snd_soc_dai_ops wsa885x_i2c_dai_ops = { + .hw_params = codec_hw_params, + .set_tdm_slot = codec_set_tdm_slot, + .set_sysclk = codec_set_sysclk, + .mute_stream = codec_mute_stream, + .hw_free = codec_hw_free, +}; + +static struct snd_soc_dai_driver wsa885x_i2c_dai[] = { + { + .name = "wsa885x_dai_drv", + .playback = { + .stream_name = "WSA885X I2C TDM Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &wsa885x_i2c_dai_ops, + }, +}; + +static void wsa885x_gpio_powerdown(void *data) +{ + gpiod_direction_output(data, 1); +} + +static bool wsa885x_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ANA_TOP_PLL_STATUS_0: + case ANA_TOP_PLL_STATUS_1: + case SMP_AMP_CTRL_STEREO_PDE23_ACT_PS: + case SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID: + case WSA885X_INTR_STATUS0: + case WSA885X_INTR_STATUS0 + 1: + case WSA885X_INTR_STATUS0 + 2: + case WSA885X_INTR_CLEAR0: + case WSA885X_INTR_CLEAR0 + 1: + case WSA885X_INTR_CLEAR0 + 2: + return true; + default: + return false; + } +} + +static bool wsa885x_readable_register(struct device *dev, unsigned int reg) +{ + if (reg >= 0 && reg <= 0x88ff) + return true; + return false; +} + +static bool wsa885x_writeable_register(struct device *dev, unsigned int reg) +{ + if (reg >= 0 && reg <= 0x88ff) { + /* Read-only status registers */ + if (reg == ANA_TOP_PLL_STATUS_0 || + reg == WSA885X_INTR_STATUS0 || + reg == WSA885X_INTR_STATUS0 + 1 || + reg == WSA885X_INTR_STATUS0 + 2 || + reg == SMP_AMP_CTRL_STEREO_PDE23_ACT_PS || + reg == SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID) + return false; + return true; + } + return false; +} + +static const struct regmap_config regmap_cfg = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x88FF, + .ranges = regmap_ranges, + .num_ranges = ARRAY_SIZE(regmap_ranges), + .reg_defaults = codec_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(codec_reg_defaults), + .volatile_reg = wsa885x_volatile_register, + .writeable_reg = wsa885x_writeable_register, + .readable_reg = wsa885x_readable_register, + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static int wsa885x_component_probe(struct snd_soc_component *component) +{ + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + wsa885x->component = component; + snd_soc_component_init_regmap(component, wsa885x->regmap); + /* Enable interrupts */ + regmap_write(wsa885x->regmap, DIG_CTRL1_SPMI_PAD_GPIO2_CTL, 0x2e); + regmap_write(wsa885x->regmap, DIG_CTRL1_INTR_MODE, 0x01); + regmap_write(wsa885x->regmap, DIG_CTRL1_PIN_CT, 0x04); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0, 0x00); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0 + 1, 0x00); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0 + 2, 0xf8); + + return 0; +} + +static void wsa885x_component_remove(struct snd_soc_component *component) +{ + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + if (!wsa885x) + return; + + snd_soc_component_exit_regmap(component); +} + +static void wsa885x_regulator_disable(void *data) +{ + regulator_bulk_disable(SUPPLIES_NUM, data); +} + +static int wsa885x_stereo_gain_offset_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + /* UI range 0..124 maps to dB = value - 84; return slider value */ + ucontrol->value.integer.value[0] = wsa885x->stereo_voldB + 84; + return 0; +} + +static int wsa885x_stereo_gain_offset_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + long val = ucontrol->value.integer.value[0]; + + if (val < 0 || val > FU21_VOL_STEPS) { + dev_err(component->dev, "%s: Invalid range, Val: %ld\n", __func__, val); + return -EINVAL; + } + wsa885x->stereo_voldB = (int)val - 84; + dev_dbg(component->dev, "%s: Volume dB: %d\n", __func__, wsa885x->stereo_voldB); + return 0; +} + +static int wsa885x_i2c_usage_modes_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + if (!wsa885x_i2c) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa885x_i2c->usage_mode; + + return 0; +} + +static int wsa885x_i2c_usage_modes_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + if (!wsa885x_i2c) + return -EINVAL; + + wsa885x_i2c->usage_mode = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: Usage mode:%d\n", __func__, + wsa885x_i2c->usage_mode); + + return 0; +} + +static int wsa885x_i2c_rx_slot_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + ucontrol->value.enumerated.item[0] = wsa885x_i2c->rx_slot_mask; + + return 0; +} + +static int wsa885x_i2c_rx_slot_mask_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + wsa885x_i2c->rx_slot_mask = ucontrol->value.enumerated.item[0]; + + dev_dbg(component->dev, "%s: Rx channel:%d select\n", __func__, + wsa885x_i2c->rx_slot_mask); + return 0; +} + +static const struct snd_kcontrol_new wsa885x_snd_controls[] = { + SOC_SINGLE_EXT("OT23 Usage Mode", SND_SOC_NOPM, 0, 8, 0, + wsa885x_i2c_usage_modes_get, + wsa885x_i2c_usage_modes_put), + + SOC_SINGLE_EXT_TLV("SA1 FU21 Stereo Gain Offset dB", SND_SOC_NOPM, + 0, FU21_VOL_STEPS, 0, + wsa885x_stereo_gain_offset_get, + wsa885x_stereo_gain_offset_put, + fu21_digital_gain), + + SOC_SINGLE_EXT("Rx Slot Mask", SND_SOC_NOPM, 0, 4, 0, + wsa885x_i2c_rx_slot_mask_get, + wsa885x_i2c_rx_slot_mask_put), +}; + +static const struct snd_soc_component_driver wsa885x_i2c_component = { + .name = "wsa885x-i2c", + .probe = wsa885x_component_probe, + .remove = wsa885x_component_remove, + .controls = wsa885x_snd_controls, + .num_controls = ARRAY_SIZE(wsa885x_snd_controls), + .dapm_widgets = NULL, + .num_dapm_widgets = 0, + .dapm_routes = NULL, + .num_dapm_routes = 0, +}; + +static irqreturn_t handle_wsa885x_i2c_irq(int irq, void *data) +{ + struct wsa885x_i2c_priv *wsa885x = data; + + /* Handle the interrupt based on the IRQ number */ + switch (irq) { + case WSA885X_IRQ_INT_SAF2WAR: + case WSA885X_IRQ_INT_WAR2SAF: + case WSA885X_IRQ_INT_PA0_OCP: + case WSA885X_IRQ_INT_PA1_OCP: + case WSA885X_IRQ_INT_CLIP0: + case WSA885X_IRQ_INT_CLIP1: + case WSA885X_IRQ_INT_CLK_WD: + case WSA885X_IRQ_INT_BOP: + case WSA885X_IRQ_INT_UVLO: + case WSA885X_IRQ_INT_PCM_DATA0_DC: + case WSA885X_IRQ_INT_PCM_DATA1_DC: + case WSA885X_IRQ_INT_PLL_UNLOCKED: + case WSA885X_IRQ_INT_PROT_MODE_CHANGE: + case WSA885X_IRQ_INT_PB_CLOCK_VALID: + case WSA885X_IRQ_INT_SENSE_CLOCK_VALID: + break; + case WSA885X_IRQ_INT_PCM_DATA0_WD: + case WSA885X_IRQ_INT_PCM_DATA1_WD: + if (!wsa885x) + return IRQ_NONE; + if (irq == WSA885X_IRQ_INT_PCM_DATA0_WD) { + regmap_update_bits(wsa885x->regmap, 0x84A0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, 0x84A0, + 0x04, 0x01); + } else { + regmap_update_bits(wsa885x->regmap, 0x84A4, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, 0x84A4, + 0x04, 0x01); + } + break; + case WSA885X_IRQ_INT_PA0_FSM_ERR: + case WSA885X_IRQ_INT_PA1_FSM_ERR: + case WSA885X_IRQ_INT_MAIN_FSM_ERR: + if (!wsa885x) + return IRQ_NONE; + + if (irq == WSA885X_IRQ_INT_MAIN_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x08); + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x00); + } else if (irq == WSA885X_IRQ_INT_PA0_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x00); + } else if (irq == WSA885X_IRQ_INT_PA1_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x00); + } + break; + default: + dev_warn(wsa885x->dev, "Unhandled IRQ: %d\n", irq); + return IRQ_NONE; + } + + pr_err_ratelimited("%s: handled %s interrupt\n", __func__, + wsa885x_irq_names[irq]); + + return IRQ_HANDLED; +} + +static irqreturn_t wsa885x_interrupt_handler(int irq, void *data) +{ + unsigned int status[NUM_REGS]; + int i, bit, ret = IRQ_NONE; + int irq_num; + struct wsa885x_i2c_priv *wsa885x = data; + int status_reg[NUM_REGS] = { + WSA885X_INTR_STATUS0, + WSA885X_INTR_STATUS0 + 1, + WSA885X_INTR_STATUS0 + 2 + }; + int clear_reg[NUM_REGS] = { + WSA885X_INTR_CLEAR0, + WSA885X_INTR_CLEAR0 + 1, + WSA885X_INTR_CLEAR0 + 2 + }; + + pr_debug("%s: interrupt for irq = %d triggered\n", __func__, irq); + /* Read all status registers */ + for (i = 0; i < NUM_REGS; i++) { + ret = regmap_read(wsa885x->regmap, status_reg[i], &status[i]); + if (ret) { + dev_err(wsa885x->dev, "Failed to read status_reg[%d] (0x%x): %d\n", + i, status_reg[i], ret); + return IRQ_NONE; + } + } + + for (i = 0; i < NUM_REGS; i++) { + for (bit = 0; bit < 8; bit++) { + if (status[i] & (1 << bit)) { + irq_num = i * 8 + bit; + ret = handle_wsa885x_i2c_irq(irq_num, wsa885x); + /* Clear the interrupt by writing 1 to the bit */ + regmap_update_bits(wsa885x->regmap, + clear_reg[i], + (1 << bit), + (1 << bit)); + /* Optionally clear again to 0 if needed */ + regmap_update_bits(wsa885x->regmap, + clear_reg[i], + (1 << bit), 0); + } + } + } + return ret; +} + +static int wsa885x_register_irq(struct wsa885x_i2c_priv *wsa885x) +{ + int ret; + + /* Get the IRQ number for the GPIO */ + int irq_number = gpiod_to_irq(wsa885x->intr_pin); + + if (irq_number < 0) { + pr_err("Failed to get IRQ number\n"); + gpiod_put(wsa885x->intr_pin); + return irq_number; + } + + ret = devm_request_threaded_irq(wsa885x->dev, irq_number, NULL, + wsa885x_interrupt_handler, + IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_FALLING, "WSA885X I2C Interrupt", + wsa885x); + if (ret) { + dev_err(wsa885x->dev, "Failed to request IRQ for wsa885x i2c\n"); + gpiod_put(wsa885x->intr_pin); + return ret; + } + return ret; +} + +static int wsa885x_i2c_probe(struct i2c_client *client) +{ + struct wsa885x_i2c_priv *wsa885x; + const char *init_table_prop = "wsa885x-init-table"; + int ret, i; + struct device *dev = &client->dev; + + wsa885x = devm_kzalloc(&client->dev, sizeof(struct wsa885x_i2c_priv), + GFP_KERNEL); + if (!wsa885x) + return -ENOMEM; + + wsa885x->client = client; + wsa885x->dev = dev; + wsa885x->stereo_voldB = -84; + wsa885x->regmap = devm_regmap_init_i2c(client, ®map_cfg); + atomic_set(&wsa885x->open_count, 0); + + if (IS_ERR(wsa885x->regmap)) + return PTR_ERR(wsa885x->regmap); + + wsa885x->init_table_size = + of_property_count_u32_elems(dev->of_node, init_table_prop); + + if (wsa885x->init_table_size <= 0) { + dev_err(dev, "%s: Failed to count elements from %s\n", + __func__, init_table_prop); + return -EINVAL; + } + + if (wsa885x->init_table_size % 2 != 0) { + dev_err(dev, "%s: Invalid number of elements in %s\n", + __func__, init_table_prop); + return -EINVAL; + } + + wsa885x->init_table = devm_kzalloc( + dev, wsa885x->init_table_size * sizeof(u32), GFP_KERNEL); + if (!wsa885x->init_table) + return -ENOMEM; + + if (of_property_read_u32_array(dev->of_node, init_table_prop, + wsa885x->init_table, + wsa885x->init_table_size)) { + dev_err(dev, + "%s: Failed to read %s\n", + __func__, init_table_prop); + return -EINVAL; + } + + ret = of_property_read_u32(dev->of_node, "qcom,battery_config", &wsa885x->batt_conf); + if (ret) { + dev_err(dev, "battery_config not specified, 1S is default: %d\n", ret); + wsa885x->batt_conf = batt_1s; + } + + for (i = 0; i < SUPPLIES_NUM; i++) + wsa885x->supplies[i].supply = supply_name[i]; + + ret = devm_regulator_bulk_get(dev, SUPPLIES_NUM, wsa885x->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + + ret = regulator_bulk_enable(SUPPLIES_NUM, wsa885x->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulators\n"); + + ret = devm_add_action_or_reset(dev, wsa885x_regulator_disable, + wsa885x->supplies); + if (ret) { + dev_err(dev, "failed to devm_add_action_or_reset, %d\n", ret); + return ret; + } + + wsa885x->sd_n = + devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); + if (IS_ERR(wsa885x->sd_n)) + return dev_err_probe(dev, PTR_ERR(wsa885x->sd_n), + "Shutdown Control GPIO not found\n"); + + ret = wsa885x_gpio_set(wsa885x, false); + if (ret != 0) + return ret; + + ret = devm_add_action_or_reset(dev, wsa885x_gpio_powerdown, + wsa885x->sd_n); + if (ret) { + dev_err(dev, "failed to devm_add_action_or_reset, %d\n", ret); + return ret; + } + + ret = devm_snd_soc_register_component(dev, &wsa885x_i2c_component, wsa885x_i2c_dai, + ARRAY_SIZE(wsa885x_i2c_dai)); + if (ret) { + dev_err(dev, "Codec component registration failed\n"); + } else { + dev_dbg(dev, "Codec component:dai %s registration success!\n", + wsa885x_i2c_dai[0].name); + } + + i2c_set_clientdata(client, wsa885x); + + wsa885x->intr_pin = devm_gpiod_get_optional(dev, "interrupt", GPIOD_IN); + if (IS_ERR(wsa885x->intr_pin)) { + ret = PTR_ERR(wsa885x->intr_pin); + dev_err(dev, "Failed to get interrupt pin, %d\n", ret); + return ret; + } + + ret = wsa885x_register_irq(wsa885x); + if (ret) + dev_err(dev, "wsa885x irq registration failed ret: %d\n", ret); + + return ret; +} + +static const struct of_device_id wsa885x_i2c_dt_match[] = { + { + .compatible = "qcom,wsa885x-i2c", + }, + {}}; + +static const struct i2c_device_id wsa885x_id_i2c[] = { + {"wsa885x_i2c", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, wsa885x_id_i2c); + +static struct i2c_driver i2c_slave_driver = { + .driver = { + .name = "wsa885x_i2c", + .of_match_table = wsa885x_i2c_dt_match, + }, + .probe = wsa885x_i2c_probe, + .id_table = wsa885x_id_i2c, +}; + +module_i2c_driver(i2c_slave_driver); + +MODULE_DESCRIPTION("ASoC WSA8855-I2C Smart PA Codec Driver"); +MODULE_LICENSE("GPL"); From b8361e8a6ca56fde1d47f2246557a00956d435f2 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 11 May 2026 12:07:27 +0530 Subject: [PATCH 0698/1058] arm64: defconfig: Enable WSA885X-I2C and PM4125 Shikra EVK boards Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 344e3b3a5052e..c02157e9c9d4b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1097,6 +1097,8 @@ CONFIG_SND_MESON_AXG_SOUND_CARD=m CONFIG_SND_MESON_GX_SOUND_CARD=m CONFIG_SND_SOC_QCOM=m CONFIG_SND_SOC_APQ8016_SBC=m +CONFIG_SND_SOC_PM4125=m +CONFIG_SND_SOC_PM4125_SDW=m CONFIG_SND_SOC_QDSP6_USB=m CONFIG_SND_SOC_MSM8996=m CONFIG_SND_SOC_SDM845=m @@ -1175,6 +1177,7 @@ CONFIG_SND_SOC_WM8978=m CONFIG_SND_SOC_WSA881X=m CONFIG_SND_SOC_WSA883X=m CONFIG_SND_SOC_WSA884X=m +CONFIG_SND_SOC_WSA885X_I2C=m CONFIG_SND_SOC_NAU8822=m CONFIG_SND_SOC_LPASS_WSA_MACRO=m CONFIG_SND_SOC_LPASS_VA_MACRO=m From 4ca536f6fff767ebbf53d386da188982824984ac Mon Sep 17 00:00:00 2001 From: Anandu Krishnan E Date: Thu, 14 May 2026 18:00:08 +0530 Subject: [PATCH 0699/1058] misc: fastrpc: fix NULL dereference on coherent sessions in fastrpc_map_attach() Commit c7d8100749c6 introduced a brace-less if that skips the dma_buf_map_attachment_unlocked() call when sess->coherent is true, leaving 'table' uninitialized. The unconditional IS_ERR(table) check that follows does not catch NULL, so execution continues with a NULL sg_table, causing a level-0 translation fault when the sgl pointer is dereferenced. Remove the guard; the mapping is always needed to obtain DMA addresses consumed by the rest of the function. Signed-off-by: Anandu Krishnan E --- drivers/misc/fastrpc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index ada424aa50cd9..81dbfc72d0da8 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -881,7 +881,6 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, err = PTR_ERR(map->attach); goto attach_err; } - if (!sess->coherent) table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL); if (IS_ERR(table)) { err = PTR_ERR(table); From 0765b9ed2f1cdbe0a4cc6852c17f6fae41556015 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 11 May 2026 16:30:00 +0530 Subject: [PATCH 0700/1058] dt-bindings: regulator: qcom,usb-vbus-regulator: add qcom,pm4125-vbus-reg The pm4125 PMIC uses a different USB VBUS register layout than pm8150b. It uses a 2-bit VBOOST voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V and 5.0 V, instead of a current-limit selector. Move qcom,pm4125-vbus-reg from the pm8150b fallback items list into the standalone enum since the driver handles it with its own match-data and register layout. Make regulator-min/max-microamp conditional so they are only required for current-limit variants (pm8150b, pm6150, pm7250b, pmi632). Add an if/then condition for qcom,pm4125-vbus-reg requiring regulator-min/ max-microvolt instead, and update the pm4125 example accordingly. Signed-off-by: Rakesh Kota --- .../regulator/qcom,usb-vbus-regulator.yaml | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index fcefc722ee2a4..d34b378517378 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -14,6 +14,13 @@ description: | regulator will be enabled in situations where the device is required to provide power to the connected peripheral. + The pm8150b variant uses an OTG current-limit selector, supporting limits + of 500 mA, 1000 mA, 1500 mA, 2000 mA, 2500 mA and 3000 mA. + + The pm4125 variant uses a different register layout with a 2-bit VBOOST + voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V + and 5.0 V. + allOf: - $ref: regulator.yaml# @@ -22,9 +29,9 @@ properties: oneOf: - enum: - qcom,pm8150b-vbus-reg + - qcom,pm4125-vbus-reg - items: - enum: - - qcom,pm4125-vbus-reg - qcom,pm6150-vbus-reg - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg @@ -34,11 +41,33 @@ properties: maxItems: 1 description: VBUS output base address +if: + properties: + compatible: + contains: + enum: + - qcom,pm8150b-vbus-reg + - qcom,pm6150-vbus-reg + - qcom,pm7250b-vbus-reg + - qcom,pmi632-vbus-reg +then: + required: + - regulator-min-microamp + - regulator-max-microamp + +if: + properties: + compatible: + contains: + const: qcom,pm4125-vbus-reg +then: + required: + - regulator-min-microvolt + - regulator-max-microvolt + required: - compatible - reg - - regulator-min-microamp - - regulator-max-microamp unevaluatedProperties: false @@ -55,4 +84,16 @@ examples: regulator-max-microamp = <3000000>; }; }; + - | + pmic { + #address-cells = <1>; + #size-cells = <0>; + + usb-vbus-regulator@5000 { + compatible = "qcom,pm4125-vbus-reg"; + reg = <0x1100>; + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; + }; + }; ... From c0225e0ab13da356ceb0fc83feaaf1f0b398e0cb Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 11 May 2026 16:32:16 +0530 Subject: [PATCH 0701/1058] regulator: qcom_usb_vbus: add support for qcom,pm4125-vbus-reg The PM4125 PMIC uses a different register layout for USB VBUS control compared to PM8150B. On PM4125, CMD_OTG is at offset 0x50, OTG_CFG is at 0x56, and offset 0x52 is a 2-bit VBOOST voltage selector rather than a current-limit selector. Introduce per-compatible regulator descriptor data to accommodate these differences. This keeps the existing PM8150B current-limit logic intact while adding a dedicated voltage-selector path for PM4125. Signed-off-by: Rakesh Kota --- drivers/regulator/qcom_usb_vbus-regulator.c | 102 +++++++++++++++++--- 1 file changed, 88 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index cd94ed67621fe..3d425452a0b35 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -20,10 +20,35 @@ #define OTG_CFG 0x53 #define OTG_EN_SRC_CFG BIT(1) +#define PM4125_CMD_OTG 0x50 +#define PM4125_VBOOST_CFG 0x52 +#define PM4125_VBOOST_CFG_MASK GENMASK(1, 0) +#define PM4125_OTG_CFG 0x56 +#define PM4125_OTG_EN_SRC_CFG BIT(0) + +struct qcom_usb_vbus_reg_data { + u16 cmd_otg; + u16 otg_cfg; + u8 otg_en_src_cfg; + u16 csel_reg; + u8 csel_mask; + const unsigned int *curr_table; + unsigned int n_current_limits; + u16 vsel_reg; + u8 vsel_mask; + const unsigned int *volt_table; + unsigned int n_voltages; + const struct regulator_ops *ops; +}; + static const unsigned int curr_table[] = { 500000, 1000000, 1500000, 2000000, 2500000, 3000000, }; +static const unsigned int pm4125_vboost_table[] = { + 4250000, 4500000, 4750000, 5000000, +}; + static const struct regulator_ops qcom_usb_vbus_reg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -32,19 +57,43 @@ static const struct regulator_ops qcom_usb_vbus_reg_ops = { .set_current_limit = regulator_set_current_limit_regmap, }; -static struct regulator_desc qcom_usb_vbus_rdesc = { - .name = "usb_vbus", - .ops = &qcom_usb_vbus_reg_ops, - .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, +static const struct regulator_ops qcom_usb_vbus_pm4125_reg_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_table, +}; + +static const struct qcom_usb_vbus_reg_data pm8150b_data = { + .cmd_otg = CMD_OTG, + .otg_cfg = OTG_CFG, + .otg_en_src_cfg = OTG_EN_SRC_CFG, + .csel_reg = OTG_CURRENT_LIMIT_CFG, + .csel_mask = OTG_CURRENT_LIMIT_MASK, .curr_table = curr_table, .n_current_limits = ARRAY_SIZE(curr_table), + .ops = &qcom_usb_vbus_reg_ops, +}; + +static const struct qcom_usb_vbus_reg_data pm4125_data = { + .cmd_otg = PM4125_CMD_OTG, + .otg_cfg = PM4125_OTG_CFG, + .otg_en_src_cfg = PM4125_OTG_EN_SRC_CFG, + .vsel_reg = PM4125_VBOOST_CFG, + .vsel_mask = PM4125_VBOOST_CFG_MASK, + .volt_table = pm4125_vboost_table, + .n_voltages = ARRAY_SIZE(pm4125_vboost_table), + .ops = &qcom_usb_vbus_pm4125_reg_ops, }; static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct qcom_usb_vbus_reg_data *data; struct regulator_dev *rdev; + struct regulator_desc *rdesc; struct regmap *regmap; struct regulator_config config = { }; struct regulator_init_data *init_data; @@ -57,27 +106,51 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) return ret; } + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + regmap = dev_get_regmap(dev->parent, NULL); if (!regmap) { dev_err(dev, "Failed to get regmap\n"); return -ENOENT; } - init_data = of_get_regulator_init_data(dev, dev->of_node, - &qcom_usb_vbus_rdesc); + rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); + if (!rdesc) + return -ENOMEM; + + rdesc->name = "usb_vbus"; + rdesc->ops = data->ops; + rdesc->owner = THIS_MODULE; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->enable_reg = base + data->cmd_otg; + rdesc->enable_mask = OTG_EN; + + if (data->curr_table) { + rdesc->curr_table = data->curr_table; + rdesc->n_current_limits = data->n_current_limits; + rdesc->csel_reg = base + data->csel_reg; + rdesc->csel_mask = data->csel_mask; + } + + if (data->volt_table) { + rdesc->volt_table = data->volt_table; + rdesc->n_voltages = data->n_voltages; + rdesc->vsel_reg = base + data->vsel_reg; + rdesc->vsel_mask = data->vsel_mask; + } + + init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc); if (!init_data) return -ENOMEM; - qcom_usb_vbus_rdesc.enable_reg = base + CMD_OTG; - qcom_usb_vbus_rdesc.enable_mask = OTG_EN; - qcom_usb_vbus_rdesc.csel_reg = base + OTG_CURRENT_LIMIT_CFG; - qcom_usb_vbus_rdesc.csel_mask = OTG_CURRENT_LIMIT_MASK; config.dev = dev; config.init_data = init_data; config.of_node = dev->of_node; config.regmap = regmap; - rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config); + rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(dev, "not able to register vbus reg %d\n", ret); @@ -85,13 +158,14 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) } /* Disable HW logic for VBUS enable */ - regmap_update_bits(regmap, base + OTG_CFG, OTG_EN_SRC_CFG, 0); + regmap_update_bits(regmap, base + data->otg_cfg, data->otg_en_src_cfg, 0); return 0; } static const struct of_device_id qcom_usb_vbus_regulator_match[] = { - { .compatible = "qcom,pm8150b-vbus-reg" }, + { .compatible = "qcom,pm8150b-vbus-reg", .data = &pm8150b_data }, + { .compatible = "qcom,pm4125-vbus-reg", .data = &pm4125_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match); From e9a9369d9564c171972ceaa4754f48ab075bbb70 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Thu, 14 May 2026 18:29:02 +0530 Subject: [PATCH 0702/1058] FROMLIST: dt-bindings: crypto: qcom,prng: Document Shikra TRNG Document shikra compatible for the True Random Number Generator. Link: https://lore.kernel.org/lkml/20260514-shikra_rng-v1-1-4ea721a1429a@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index dc270c8aedf3a..5de52d7a745c3 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -30,6 +30,7 @@ properties: - qcom,sa8255p-trng - qcom,sa8775p-trng - qcom,sc7280-trng + - qcom,shikra-trng - qcom,sm8450-trng - qcom,sm8550-trng - qcom,sm8650-trng From d0d560328a7e88aa332fb548248d8cbde610df9d Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Fri, 15 May 2026 00:03:03 +0530 Subject: [PATCH 0703/1058] FROMLIST: dt-bindings: crypto: qcom-qce: Document the Shikra crypto engine Document the crypto engine on the Shikra platform. Link:https://lore.kernel.org/lkml/20260515-shikra_qcrypto-v1-1-80f07b345c29@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 08febd66c22ba..5a653757ee752 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -54,6 +54,7 @@ properties: - qcom,qcs8300-qce - qcom,sa8775p-qce - qcom,sc7280-qce + - qcom,shikra-qce - qcom,sm6350-qce - qcom,sm8250-qce - qcom,sm8350-qce From f9dbe6592e6d48984bf37f35f6a0cb43fe604d36 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Fri, 15 May 2026 00:03:58 +0530 Subject: [PATCH 0704/1058] dt-bindings: bam-dma: Increase maxItems to seven for iommus Shikra bam dma engine support seven iommu entries. Increase maxItems property for iommus to pass dtbs_check errors. Link: https://lore.kernel.org/lkml/20260515-shikra_qcrypto-v1-2-80f07b345c29@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml index 0923fb189ada9..e72adc172af10 100644 --- a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml +++ b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml @@ -48,7 +48,7 @@ properties: iommus: minItems: 1 - maxItems: 6 + maxItems: 7 num-channels: $ref: /schemas/types.yaml#/definitions/uint32 From e52b25eaab983bf7a6ba407cf4b1209559245dbd Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Wed, 13 May 2026 18:00:30 +0530 Subject: [PATCH 0705/1058] dt-bindings: crypto: qcom,inline-crypto-engine: Document Shikra ICE Document the Inline Crypto Engine (ICE) on the Shikra platform. Signed-off-by: Kuldeep Singh --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index db895c50e2d25..fa16916714077 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -21,6 +21,7 @@ properties: - qcom,sa8775p-inline-crypto-engine - qcom,sc7180-inline-crypto-engine - qcom,sc7280-inline-crypto-engine + - qcom,shikra-inline-crypto-engine - qcom,sm8450-inline-crypto-engine - qcom,sm8550-inline-crypto-engine - qcom,sm8650-inline-crypto-engine From 323d424c9a6c1778a650dc0e0ed58e1c353f5b27 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 8 May 2026 17:21:41 +0530 Subject: [PATCH 0706/1058] clk: qcom: common: Register reset controller only when resets are present Some clock controller descriptors do not provide any reset lines. Avoid registering a reset controller when desc->num_resets is zero by making the registration conditional. Signed-off-by: Imran Shaik --- drivers/clk/qcom/common.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index eec369d2173b5..be9b6ebb2fffd 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -359,17 +359,19 @@ int qcom_cc_really_probe(struct device *dev, qcom_cc_clk_regs_configure(dev, desc->driver_data, regmap); } - reset = &cc->reset; - reset->rcdev.of_node = dev->of_node; - reset->rcdev.ops = &qcom_reset_ops; - reset->rcdev.owner = dev->driver->owner; - reset->rcdev.nr_resets = desc->num_resets; - reset->regmap = regmap; - reset->reset_map = desc->resets; - - ret = devm_reset_controller_register(dev, &reset->rcdev); - if (ret) - goto put_rpm; + if (desc->num_resets) { + reset = &cc->reset; + reset->rcdev.of_node = dev->of_node; + reset->rcdev.ops = &qcom_reset_ops; + reset->rcdev.owner = dev->driver->owner; + reset->rcdev.nr_resets = desc->num_resets; + reset->regmap = regmap; + reset->reset_map = desc->resets; + + ret = devm_reset_controller_register(dev, &reset->rcdev); + if (ret) + goto put_rpm; + } if (desc->gdscs && desc->num_gdscs) { scd = devm_kzalloc(dev, sizeof(*scd), GFP_KERNEL); From e2041dad6a1057dc3200a8b8bfce8175528639cf Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 12 May 2026 18:41:56 +0530 Subject: [PATCH 0707/1058] clk: qcom: common: Skip NULL clock hw entries during registration Some Qualcomm clock controller descriptors may contain NULL entries in the clk_hws array. Skip such entries when registering clock hardware to avoid passing NULL pointers to the clock framework. Signed-off-by: Imran Shaik --- drivers/clk/qcom/common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index be9b6ebb2fffd..000bfdcc5391f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -408,6 +408,9 @@ int qcom_cc_really_probe(struct device *dev, qcom_cc_drop_protected(dev, cc); for (i = 0; i < num_clk_hws; i++) { + if (!clk_hws[i]) + continue; + ret = devm_clk_hw_register(dev, clk_hws[i]); if (ret) goto put_rpm; From c16751bfdbf437e460408e9cf6ddab6112f81e08 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 7 May 2026 14:05:07 +0530 Subject: [PATCH 0708/1058] dt-bindings: clock: qcom: Add GCC LPASS clocks support for Shikra Add GCC LPASS clocks support for Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- include/dt-bindings/clock/qcom,shikra-gcc.h | 203 ++++++++++---------- 1 file changed, 103 insertions(+), 100 deletions(-) diff --git a/include/dt-bindings/clock/qcom,shikra-gcc.h b/include/dt-bindings/clock/qcom,shikra-gcc.h index 2e88a9cd9f535..dc55e5652caae 100644 --- a/include/dt-bindings/clock/qcom,shikra-gcc.h +++ b/include/dt-bindings/clock/qcom,shikra-gcc.h @@ -119,106 +119,109 @@ #define GCC_GPU_CFG_AHB_CLK 109 #define GCC_GPU_GPLL0_CLK_SRC 110 #define GCC_GPU_GPLL0_DIV_CLK_SRC 111 -#define GCC_GPU_MEMNOC_GFX_CLK 112 -#define GCC_GPU_SMMU_VOTE_CLK 113 -#define GCC_GPU_SNOC_DVM_GFX_CLK 114 -#define GCC_GPU_THROTTLE_CORE_CLK 115 -#define GCC_MMU_TCU_VOTE_CLK 116 -#define GCC_PCIE_AUX_CLK 117 -#define GCC_PCIE_AUX_CLK_SRC 118 -#define GCC_PCIE_AUX_PHY_CLK_SRC 119 -#define GCC_PCIE_CFG_AHB_CLK 120 -#define GCC_PCIE_CLKREF_EN 121 -#define GCC_PCIE_MSTR_AXI_CLK 122 -#define GCC_PCIE_PIPE_CLK 123 -#define GCC_PCIE_PIPE_CLK_SRC 124 -#define GCC_PCIE_RCHNG_PHY_CLK 125 -#define GCC_PCIE_RCHNG_PHY_CLK_SRC 126 -#define GCC_PCIE_SLEEP_CLK 127 -#define GCC_PCIE_SLV_AXI_CLK 128 -#define GCC_PCIE_SLV_Q2A_AXI_CLK 129 -#define GCC_PCIE_TBU_CLK 130 -#define GCC_PCIE_THROTTLE_CORE_CLK 131 -#define GCC_PCIE_THROTTLE_XO_CLK 132 -#define GCC_PCIE_TILE_AXI_SYS_NOC_CLK 133 -#define GCC_PDM2_CLK 134 -#define GCC_PDM2_CLK_SRC 135 -#define GCC_PDM_AHB_CLK 136 -#define GCC_PDM_XO4_CLK 137 -#define GCC_PWM0_XO512_CLK 138 -#define GCC_QMIP_CAMERA_NRT_AHB_CLK 139 -#define GCC_QMIP_CAMERA_RT_AHB_CLK 140 -#define GCC_QMIP_DISP_AHB_CLK 141 -#define GCC_QMIP_GPU_CFG_AHB_CLK 142 -#define GCC_QMIP_PCIE_CFG_AHB_CLK 143 -#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 144 -#define GCC_QUPV3_WRAP0_CORE_2X_CLK 145 -#define GCC_QUPV3_WRAP0_CORE_CLK 146 -#define GCC_QUPV3_WRAP0_S0_CLK 147 -#define GCC_QUPV3_WRAP0_S0_CLK_SRC 148 -#define GCC_QUPV3_WRAP0_S1_CLK 149 -#define GCC_QUPV3_WRAP0_S1_CLK_SRC 150 -#define GCC_QUPV3_WRAP0_S2_CLK 151 -#define GCC_QUPV3_WRAP0_S2_CLK_SRC 152 -#define GCC_QUPV3_WRAP0_S3_CLK 153 -#define GCC_QUPV3_WRAP0_S3_CLK_SRC 154 -#define GCC_QUPV3_WRAP0_S4_CLK 155 -#define GCC_QUPV3_WRAP0_S4_CLK_SRC 156 -#define GCC_QUPV3_WRAP0_S5_CLK 157 -#define GCC_QUPV3_WRAP0_S5_CLK_SRC 158 -#define GCC_QUPV3_WRAP0_S6_CLK 159 -#define GCC_QUPV3_WRAP0_S6_CLK_SRC 160 -#define GCC_QUPV3_WRAP0_S7_CLK 161 -#define GCC_QUPV3_WRAP0_S7_CLK_SRC 162 -#define GCC_QUPV3_WRAP0_S8_CLK 163 -#define GCC_QUPV3_WRAP0_S8_CLK_SRC 164 -#define GCC_QUPV3_WRAP0_S9_CLK 165 -#define GCC_QUPV3_WRAP0_S9_CLK_SRC 166 -#define GCC_QUPV3_WRAP_0_M_AHB_CLK 167 -#define GCC_QUPV3_WRAP_0_S_AHB_CLK 168 -#define GCC_SDCC1_AHB_CLK 169 -#define GCC_SDCC1_APPS_CLK 170 -#define GCC_SDCC1_APPS_CLK_SRC 171 -#define GCC_SDCC1_ICE_CORE_CLK 172 -#define GCC_SDCC1_ICE_CORE_CLK_SRC 173 -#define GCC_SDCC2_AHB_CLK 174 -#define GCC_SDCC2_APPS_CLK 175 -#define GCC_SDCC2_APPS_CLK_SRC 176 -#define GCC_SYS_NOC_CPUSS_AHB_CLK 177 -#define GCC_SYS_NOC_USB2_PRIM_AXI_CLK 178 -#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 179 -#define GCC_TSCSS_AHB_CLK 180 -#define GCC_TSCSS_CLK_SRC 181 -#define GCC_TSCSS_CNTR_CLK 182 -#define GCC_TSCSS_ETU_CLK 183 -#define GCC_UFS_CLKREF_EN 184 -#define GCC_USB20_MASTER_CLK 185 -#define GCC_USB20_MASTER_CLK_SRC 186 -#define GCC_USB20_MOCK_UTMI_CLK 187 -#define GCC_USB20_MOCK_UTMI_CLK_SRC 188 -#define GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC 189 -#define GCC_USB20_SLEEP_CLK 190 -#define GCC_USB30_PRIM_MASTER_CLK 191 -#define GCC_USB30_PRIM_MASTER_CLK_SRC 192 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK 193 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 194 -#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 195 -#define GCC_USB30_PRIM_SLEEP_CLK 196 -#define GCC_USB3_PRIM_CLKREF_EN 197 -#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 198 -#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 199 -#define GCC_USB3_PRIM_PHY_PIPE_CLK 200 -#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 201 -#define GCC_VCODEC0_AXI_CLK 202 -#define GCC_VENUS_AHB_CLK 203 -#define GCC_VENUS_CTL_AXI_CLK 204 -#define GCC_VIDEO_AHB_CLK 205 -#define GCC_VIDEO_AXI0_CLK 206 -#define GCC_VIDEO_THROTTLE_CORE_CLK 207 -#define GCC_VIDEO_VCODEC0_SYS_CLK 208 -#define GCC_VIDEO_VENUS_CLK_SRC 209 -#define GCC_VIDEO_VENUS_CTL_CLK 210 -#define GCC_VIDEO_XO_CLK 211 +#define GCC_GPU_IREF_CLK 112 +#define GCC_GPU_MEMNOC_GFX_CLK 113 +#define GCC_GPU_SMMU_VOTE_CLK 114 +#define GCC_GPU_SNOC_DVM_GFX_CLK 115 +#define GCC_GPU_THROTTLE_CORE_CLK 116 +#define GCC_LPASS_CONFIG_CLK 117 +#define GCC_LPASS_CORE_AXIM_CLK 118 +#define GCC_MMU_TCU_VOTE_CLK 119 +#define GCC_PCIE_AUX_CLK 120 +#define GCC_PCIE_AUX_CLK_SRC 121 +#define GCC_PCIE_AUX_PHY_CLK_SRC 122 +#define GCC_PCIE_CFG_AHB_CLK 123 +#define GCC_PCIE_CLKREF_EN 124 +#define GCC_PCIE_MSTR_AXI_CLK 125 +#define GCC_PCIE_PIPE_CLK 126 +#define GCC_PCIE_PIPE_CLK_SRC 127 +#define GCC_PCIE_RCHNG_PHY_CLK 128 +#define GCC_PCIE_RCHNG_PHY_CLK_SRC 129 +#define GCC_PCIE_SLEEP_CLK 130 +#define GCC_PCIE_SLV_AXI_CLK 131 +#define GCC_PCIE_SLV_Q2A_AXI_CLK 132 +#define GCC_PCIE_TBU_CLK 133 +#define GCC_PCIE_THROTTLE_CORE_CLK 134 +#define GCC_PCIE_THROTTLE_XO_CLK 135 +#define GCC_PCIE_TILE_AXI_SYS_NOC_CLK 136 +#define GCC_PDM2_CLK 137 +#define GCC_PDM2_CLK_SRC 138 +#define GCC_PDM_AHB_CLK 139 +#define GCC_PDM_XO4_CLK 140 +#define GCC_PWM0_XO512_CLK 141 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 142 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 143 +#define GCC_QMIP_DISP_AHB_CLK 144 +#define GCC_QMIP_GPU_CFG_AHB_CLK 145 +#define GCC_QMIP_PCIE_CFG_AHB_CLK 146 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 147 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 148 +#define GCC_QUPV3_WRAP0_CORE_CLK 149 +#define GCC_QUPV3_WRAP0_S0_CLK 150 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 151 +#define GCC_QUPV3_WRAP0_S1_CLK 152 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 153 +#define GCC_QUPV3_WRAP0_S2_CLK 154 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 155 +#define GCC_QUPV3_WRAP0_S3_CLK 156 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 157 +#define GCC_QUPV3_WRAP0_S4_CLK 158 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 159 +#define GCC_QUPV3_WRAP0_S5_CLK 160 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 161 +#define GCC_QUPV3_WRAP0_S6_CLK 162 +#define GCC_QUPV3_WRAP0_S6_CLK_SRC 163 +#define GCC_QUPV3_WRAP0_S7_CLK 164 +#define GCC_QUPV3_WRAP0_S7_CLK_SRC 165 +#define GCC_QUPV3_WRAP0_S8_CLK 166 +#define GCC_QUPV3_WRAP0_S8_CLK_SRC 167 +#define GCC_QUPV3_WRAP0_S9_CLK 168 +#define GCC_QUPV3_WRAP0_S9_CLK_SRC 169 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 170 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 171 +#define GCC_SDCC1_AHB_CLK 172 +#define GCC_SDCC1_APPS_CLK 173 +#define GCC_SDCC1_APPS_CLK_SRC 174 +#define GCC_SDCC1_ICE_CORE_CLK 175 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 176 +#define GCC_SDCC2_AHB_CLK 177 +#define GCC_SDCC2_APPS_CLK 178 +#define GCC_SDCC2_APPS_CLK_SRC 179 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 180 +#define GCC_SYS_NOC_USB2_PRIM_AXI_CLK 181 +#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 182 +#define GCC_TSCSS_AHB_CLK 183 +#define GCC_TSCSS_CLK_SRC 184 +#define GCC_TSCSS_CNTR_CLK 185 +#define GCC_TSCSS_ETU_CLK 186 +#define GCC_UFS_CLKREF_EN 187 +#define GCC_USB20_MASTER_CLK 188 +#define GCC_USB20_MASTER_CLK_SRC 189 +#define GCC_USB20_MOCK_UTMI_CLK 190 +#define GCC_USB20_MOCK_UTMI_CLK_SRC 191 +#define GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC 192 +#define GCC_USB20_SLEEP_CLK 193 +#define GCC_USB30_PRIM_MASTER_CLK 194 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 195 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 196 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 197 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 198 +#define GCC_USB30_PRIM_SLEEP_CLK 199 +#define GCC_USB3_PRIM_CLKREF_EN 200 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 201 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 202 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 203 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 204 +#define GCC_VCODEC0_AXI_CLK 205 +#define GCC_VENUS_AHB_CLK 206 +#define GCC_VENUS_CTL_AXI_CLK 207 +#define GCC_VIDEO_AHB_CLK 208 +#define GCC_VIDEO_AXI0_CLK 209 +#define GCC_VIDEO_THROTTLE_CORE_CLK 210 +#define GCC_VIDEO_VCODEC0_SYS_CLK 211 +#define GCC_VIDEO_VENUS_CLK_SRC 212 +#define GCC_VIDEO_VENUS_CTL_CLK 213 +#define GCC_VIDEO_XO_CLK 214 /* GCC power domains */ #define GCC_CAMSS_TOP_GDSC 0 From 3ea2287e155e54402bf25071cf0c3bf966bf77cd Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 7 May 2026 14:05:30 +0530 Subject: [PATCH 0709/1058] clk: qcom: gcc-shikra: Mark GCC LPASS clocks as critical The GCC LPASS clocks must be enabled to access audio core clock controller registers. Hence, mark them as critical on Qualcomm Shikra SoCs. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gcc-shikra.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-shikra.c b/drivers/clk/qcom/gcc-shikra.c index 8834618354882..65cd42e0334de 100644 --- a/drivers/clk/qcom/gcc-shikra.c +++ b/drivers/clk/qcom/gcc-shikra.c @@ -4347,6 +4347,8 @@ static u32 gcc_shikra_critical_cbcrs[] = { 0x1702c, /* GCC_DISP_XO_CLK */ 0x36004, /* GCC_GPU_CFG_AHB_CLK */ 0x36100, /* GCC_GPU_IREF_CLK */ + 0x3a00c, /* GCC_LPASS_CONFIG_CLK */ + 0x3a008, /* GCC_LPASS_CORE_AXIM_CLK */ 0x79004, /* GCC_SYS_NOC_CPUSS_AHB_CLK */ 0x17004, /* GCC_VIDEO_AHB_CLK */ 0x17024, /* GCC_VIDEO_XO_CLK */ From 179b51b27cc029c62aa28f82e963dfc7a3e3ac04 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 7 May 2026 14:35:05 +0530 Subject: [PATCH 0710/1058] dt-bindings: clock: qcom: Add Qualcomm Shikra Audio Core Clock Controller Add device tree bindings for the Audio Core clock controller on Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- .../clock/qcom,shikra-audiocorecc.yaml | 62 +++++++++++++++++++ .../clock/qcom,shikra-audiocorecc.h | 49 +++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml create mode 100644 include/dt-bindings/clock/qcom,shikra-audiocorecc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml new file mode 100644 index 0000000000000..2ed1d9d871175 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,shikra-audiocorecc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Audio Core Clock & Reset Controller for Qualcomm Shikra SoC + +maintainers: + - Imran Shaik + +description: | + Audio core clock control module provides the clocks and resets + on Qualcomm Shikra SoC platform. + + See also: + - include/dt-bindings/clock/qcom,shikra-audiocorecc.h + +properties: + compatible: + enum: + - qcom,shikra-cqm-audiocorecc + - qcom,shikra-cqs-audiocorecc + + clocks: + items: + - description: Board XO source + - description: Board sleep clock + - description: Audio ref clock source + + reg: + maxItems: 2 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@a0a0000 { + compatible = "qcom,shikra-cqm-audiocorecc"; + reg = <0x0a0a0000 0x10000>, + <0x0a0b4000 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&aud_ref_clk_src>; + #clock-cells = <1>; + #reset-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,shikra-audiocorecc.h b/include/dt-bindings/clock/qcom,shikra-audiocorecc.h new file mode 100644 index 0000000000000..bc77d7a3946ea --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-audiocorecc.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_AUDIO_CORE_CC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_AUDIO_CORE_CC_SHIKRA_H + +/* AUDIO_CORE_CC clocks */ +#define AUDIO_CORE_CC_DIG_PLL 0 +#define AUDIO_CORE_CC_DIG_PLL_OUT_AUX 1 +#define AUDIO_CORE_CC_DIG_PLL_OUT_AUX2 2 +#define AUDIO_CORE_CC_AIF_IF0_CLK_SRC 3 +#define AUDIO_CORE_CC_AIF_IF0_EBIT_CLK 4 +#define AUDIO_CORE_CC_AIF_IF0_IBIT_CLK 5 +#define AUDIO_CORE_CC_AIF_IF1_CLK_SRC 6 +#define AUDIO_CORE_CC_AIF_IF1_EBIT_CLK 7 +#define AUDIO_CORE_CC_AIF_IF1_IBIT_CLK 8 +#define AUDIO_CORE_CC_AIF_IF2_CLK_SRC 9 +#define AUDIO_CORE_CC_AIF_IF2_EBIT_CLK 10 +#define AUDIO_CORE_CC_AIF_IF2_IBIT_CLK 11 +#define AUDIO_CORE_CC_AIF_IF3_CLK_SRC 12 +#define AUDIO_CORE_CC_AIF_IF3_EBIT_CLK 13 +#define AUDIO_CORE_CC_AIF_IF3_IBIT_CLK 14 +#define AUDIO_CORE_CC_AUD_DMA_CLK 15 +#define AUDIO_CORE_CC_AUD_DMA_CLK_SRC 16 +#define AUDIO_CORE_CC_AUD_DMA_MEM_CLK 17 +#define AUDIO_CORE_CC_BUS_CLK 18 +#define AUDIO_CORE_CC_BUS_CLK_SRC 19 +#define AUDIO_CORE_CC_CDIV_TX_MCLK_DIV_CLK_SRC 20 +#define AUDIO_CORE_CC_EXT_MCLKA_CLK_SRC 21 +#define AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK 22 +#define AUDIO_CORE_CC_EXT_MCLKB_CLK_SRC 23 +#define AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK 24 +#define AUDIO_CORE_CC_IM_SLEEP_CLK 25 +#define AUDIO_CORE_CC_LPAIF_PCMOE_CLK 26 +#define AUDIO_CORE_CC_LPAIF_PCMOE_CLK_SRC 27 +#define AUDIO_CORE_CC_RX_MCLK_2X_CLK 28 +#define AUDIO_CORE_CC_RX_MCLK_CLK 29 +#define AUDIO_CORE_CC_SAMPLING_CLK 30 +#define AUDIO_CORE_CC_TX_MCLK_2X_CLK 31 +#define AUDIO_CORE_CC_TX_MCLK_CLK 32 +#define AUDIO_CORE_CC_TX_MCLK_RCG_CLK_SRC 33 + +/* AUDIO_CORE_CC resets */ +#define AUDIO_CORE_CSR_RX_SWR_CGCR 0 +#define AUDIO_CORE_CSR_TX_SWR_CGCR 1 + +#endif From 51e0d5141eab079af2fdf7f4b542f35bdf148284 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Wed, 6 May 2026 16:57:36 +0530 Subject: [PATCH 0711/1058] clk: qcom: Add Audio Core clock controller support on Qualcomm Shikra SoC Add support for Audio core clock controller on Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- drivers/clk/qcom/Kconfig | 11 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/audiocorecc-shikra.c | 815 ++++++++++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 drivers/clk/qcom/audiocorecc-shikra.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 31b4358c1c2e4..dfc96dc163b50 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -155,6 +155,17 @@ config CLK_NORD_GCC SPI, I2C, USB, SD/UFS, PCIe etc. The clock controller is a combination of GCC, SE_GCC, NE_GCC and NW_GCC. +config CLK_SHIKRA_AUDIOCORECC + tristate "Shikra Audio Core Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_SHIKRA_GCC + default m if ARCH_QCOM + help + Support for the Audio Core clock controller on Qualcomm Technologies, Inc + Shikra devices. + Say Y if you want to use AudioCoreCC clocks required to support audio + devices and it's functionality. + config CLK_SHIKRA_DISPCC tristate "Shikra Display Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 7be66d73c29c0..38b77a2a2712a 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_KAANAPALI_TCSRCC) += tcsrcc-kaanapali.o obj-$(CONFIG_CLK_KAANAPALI_VIDEOCC) += videocc-kaanapali.o obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o +obj-$(CONFIG_CLK_SHIKRA_AUDIOCORECC) += audiocorecc-shikra.o obj-$(CONFIG_CLK_SHIKRA_DISPCC) += dispcc-shikra.o obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o obj-$(CONFIG_CLK_SHIKRA_GPUCC) += gpucc-shikra.o diff --git a/drivers/clk/qcom/audiocorecc-shikra.c b/drivers/clk/qcom/audiocorecc-shikra.c new file mode 100644 index 0000000000000..f7655b2cbd458 --- /dev/null +++ b/drivers/clk/qcom/audiocorecc-shikra.c @@ -0,0 +1,815 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AUD_REF_CLK_SRC, +}; + +enum { + P_AUD_REF_CLK_SRC, + P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, + P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, + P_BI_TCXO, + P_SLEEP_CLK, +}; + +static const struct pll_vco spark_vco[] = { + { 500000000, 1000000000, 2 }, +}; + +/* 614.4 MHz Configuration */ +static const struct alpha_pll_config audio_core_cc_dig_pll_config = { + .l = 0x20, + .alpha = 0x0, + .vco_val = BIT(21), + .post_div_val = 0x28100, + .post_div_mask = GENMASK(17, 8), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .aux2_output_mask = BIT(2), + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x1, + .test_ctl_hi_mask = 0x1, +}; + +static struct clk_alpha_pll audio_core_cc_dig_pll = { + .offset = 0x0, + .config = &audio_core_cc_dig_pll_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_dig_pll", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_fixed_factor audio_core_cc_dig_pll_out_aux = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data) { + .name = "audio_core_cc_dig_pll_out_aux", + .parent_data = &(const struct clk_parent_data) { + .hw = &audio_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor audio_core_cc_dig_pll_out_aux2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data) { + .name = "audio_core_cc_dig_pll_out_aux2", + .parent_data = &(const struct clk_parent_data) { + .hw = &audio_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static const struct parent_map audio_core_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_AUD_REF_CLK_SRC, 1 }, + { P_SLEEP_CLK, 2 }, + { P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 4 }, + { P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 6 }, +}; + +static const struct clk_parent_data audio_core_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_AUD_REF_CLK_SRC }, + { .index = DT_SLEEP_CLK }, + { .hw = &audio_core_cc_dig_pll_out_aux.hw }, + { .hw = &audio_core_cc_dig_pll_out_aux2.hw }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aif_if0_clk_src[] = { + F(240000, P_BI_TCXO, 10, 1, 8), + F(256000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 32), + F(512000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 16), + F(768000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 8), + F(1536000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 4), + F(3072000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 2), + F(6144000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aif_if0_clk_src = { + .cmd_rcgr = 0x104c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_aif_if1_clk_src = { + .cmd_rcgr = 0x10b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_aif_if2_clk_src = { + .cmd_rcgr = 0x1114, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aif_if3_clk_src[] = { + F(240000, P_BI_TCXO, 10, 1, 8), + F(256000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 32), + F(512000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 16), + F(768000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 8), + F(1536000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 4), + F(3072000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 2), + F(6144000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + F(49152000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aif_if3_clk_src = { + .cmd_rcgr = 0x1178, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if3_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aud_dma_clk_src[] = { + F(102400000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 3, 0, 0), + F(153600000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 2, 0, 0), + F(307200000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aud_dma_clk_src = { + .cmd_rcgr = 0x1028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aud_dma_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_bus_clk_src[] = { + F(38400000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 8, 0, 0), + F(76800000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 4, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_bus_clk_src = { + .cmd_rcgr = 0x1008, + .mnd_width = 0, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_bus_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_bus_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_ext_mclka_clk_src = { + .cmd_rcgr = 0x123c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclka_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_ext_mclkb_clk_src = { + .cmd_rcgr = 0x125c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclkb_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_lpaif_pcmoe_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(15360000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 8, 0, 0), + F(30720000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 4, 0, 0), + F(61440000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 2, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_lpaif_pcmoe_clk_src = { + .cmd_rcgr = 0x12ac, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_lpaif_pcmoe_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_lpaif_pcmoe_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_tx_mclk_rcg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_tx_mclk_rcg_clk_src = { + .cmd_rcgr = 0x127c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_tx_mclk_rcg_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_rcg_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div audio_core_cc_cdiv_tx_mclk_div_clk_src = { + .reg = 0x129c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_cdiv_tx_mclk_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch audio_core_cc_aif_if0_ebit_clk = { + .halt_reg = 0x1068, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1068, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if0_ibit_clk = { + .halt_reg = 0x1064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if1_ebit_clk = { + .halt_reg = 0x10cc, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x10cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if1_ibit_clk = { + .halt_reg = 0x10c8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10c8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if2_ebit_clk = { + .halt_reg = 0x1130, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1130, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if2_ibit_clk = { + .halt_reg = 0x112c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if3_ebit_clk = { + .halt_reg = 0x1194, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1194, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if3_ibit_clk = { + .halt_reg = 0x1190, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1190, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aud_dma_clk = { + .halt_reg = 0x1040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aud_dma_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aud_dma_mem_clk = { + .halt_reg = 0x1044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_mem_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aud_dma_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_bus_clk = { + .halt_reg = 0x1020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_bus_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_bus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_ext_mclka_out_clk = { + .halt_reg = 0x1254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclka_out_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_ext_mclka_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_ext_mclkb_out_clk = { + .halt_reg = 0x1274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1274, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclkb_out_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_ext_mclkb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_im_sleep_clk = { + .halt_reg = 0x12cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_im_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_lpaif_pcmoe_clk = { + .halt_reg = 0x12c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_lpaif_pcmoe_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_lpaif_pcmoe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_rx_mclk_2x_clk = { + .halt_reg = 0x1298, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1298, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_rx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_rx_mclk_clk = { + .halt_reg = 0x12a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_rx_mclk_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_sampling_clk = { + .halt_reg = 0x1000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_sampling_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_tx_mclk_2x_clk = { + .halt_reg = 0x1294, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1294, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_tx_mclk_clk = { + .halt_reg = 0x12a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_hw *audio_core_cc_shikra_hws[] = { + [AUDIO_CORE_CC_DIG_PLL_OUT_AUX] = &audio_core_cc_dig_pll_out_aux.hw, + [AUDIO_CORE_CC_DIG_PLL_OUT_AUX2] = &audio_core_cc_dig_pll_out_aux2.hw, +}; + +static struct clk_regmap *audio_core_cc_shikra_clocks[] = { + [AUDIO_CORE_CC_AIF_IF0_CLK_SRC] = &audio_core_cc_aif_if0_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF0_EBIT_CLK] = &audio_core_cc_aif_if0_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF0_IBIT_CLK] = &audio_core_cc_aif_if0_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF1_CLK_SRC] = &audio_core_cc_aif_if1_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF1_EBIT_CLK] = &audio_core_cc_aif_if1_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF1_IBIT_CLK] = &audio_core_cc_aif_if1_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF2_CLK_SRC] = &audio_core_cc_aif_if2_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF2_EBIT_CLK] = &audio_core_cc_aif_if2_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF2_IBIT_CLK] = &audio_core_cc_aif_if2_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF3_CLK_SRC] = &audio_core_cc_aif_if3_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF3_EBIT_CLK] = &audio_core_cc_aif_if3_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF3_IBIT_CLK] = &audio_core_cc_aif_if3_ibit_clk.clkr, + [AUDIO_CORE_CC_AUD_DMA_CLK] = &audio_core_cc_aud_dma_clk.clkr, + [AUDIO_CORE_CC_AUD_DMA_CLK_SRC] = &audio_core_cc_aud_dma_clk_src.clkr, + [AUDIO_CORE_CC_AUD_DMA_MEM_CLK] = &audio_core_cc_aud_dma_mem_clk.clkr, + [AUDIO_CORE_CC_BUS_CLK] = &audio_core_cc_bus_clk.clkr, + [AUDIO_CORE_CC_BUS_CLK_SRC] = &audio_core_cc_bus_clk_src.clkr, + [AUDIO_CORE_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr, + [AUDIO_CORE_CC_DIG_PLL] = &audio_core_cc_dig_pll.clkr, + [AUDIO_CORE_CC_EXT_MCLKA_CLK_SRC] = &audio_core_cc_ext_mclka_clk_src.clkr, + [AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK] = &audio_core_cc_ext_mclka_out_clk.clkr, + [AUDIO_CORE_CC_EXT_MCLKB_CLK_SRC] = &audio_core_cc_ext_mclkb_clk_src.clkr, + [AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK] = &audio_core_cc_ext_mclkb_out_clk.clkr, + [AUDIO_CORE_CC_IM_SLEEP_CLK] = &audio_core_cc_im_sleep_clk.clkr, + [AUDIO_CORE_CC_LPAIF_PCMOE_CLK] = &audio_core_cc_lpaif_pcmoe_clk.clkr, + [AUDIO_CORE_CC_LPAIF_PCMOE_CLK_SRC] = &audio_core_cc_lpaif_pcmoe_clk_src.clkr, + [AUDIO_CORE_CC_RX_MCLK_2X_CLK] = &audio_core_cc_rx_mclk_2x_clk.clkr, + [AUDIO_CORE_CC_RX_MCLK_CLK] = &audio_core_cc_rx_mclk_clk.clkr, + [AUDIO_CORE_CC_SAMPLING_CLK] = &audio_core_cc_sampling_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_2X_CLK] = &audio_core_cc_tx_mclk_2x_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_CLK] = &audio_core_cc_tx_mclk_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_RCG_CLK_SRC] = &audio_core_cc_tx_mclk_rcg_clk_src.clkr, +}; + +static struct clk_alpha_pll *audio_core_cc_shikra_plls[] = { + &audio_core_cc_dig_pll, +}; + +static const struct regmap_config audio_core_cc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x305c, + .fast_io = true, +}; + +static const struct qcom_reset_map audio_core_cc_shikra_resets[] = { + [AUDIO_CORE_CSR_RX_SWR_CGCR] = { 0x1c }, + [AUDIO_CORE_CSR_TX_SWR_CGCR] = { 0x30 }, +}; + +static const struct regmap_config audio_core_cc_shikra_reset_regmap_config = { + .name = "audio_core_cc_shikra_reset", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = 0x34, +}; + +static struct qcom_cc_driver_data audio_core_cc_shikra_driver_data = { + .alpha_plls = audio_core_cc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(audio_core_cc_shikra_plls), +}; + +static const struct qcom_cc_desc audio_core_cc_shikra_reset_desc = { + .config = &audio_core_cc_shikra_reset_regmap_config, + .resets = audio_core_cc_shikra_resets, + .num_resets = ARRAY_SIZE(audio_core_cc_shikra_resets), +}; + +static const struct qcom_cc_desc audio_core_cc_shikra_desc = { + .config = &audio_core_cc_shikra_regmap_config, + .clk_hws = audio_core_cc_shikra_hws, + .num_clk_hws = ARRAY_SIZE(audio_core_cc_shikra_hws), + .clks = audio_core_cc_shikra_clocks, + .num_clks = ARRAY_SIZE(audio_core_cc_shikra_clocks), + .driver_data = &audio_core_cc_shikra_driver_data, +}; + +static const struct of_device_id audio_core_cc_shikra_match_table[] = { + { .compatible = "qcom,shikra-cqm-audiocorecc" }, + { .compatible = "qcom,shikra-cqs-audiocorecc" }, + { } +}; +MODULE_DEVICE_TABLE(of, audio_core_cc_shikra_match_table); + +static int audio_core_cc_shikra_probe(struct platform_device *pdev) +{ + int ret; + + ret = qcom_cc_probe_by_index(pdev, 1, &audio_core_cc_shikra_reset_desc); + if (ret) + return ret; + + if (device_is_compatible(&pdev->dev, "qcom,shikra-cqs-audiocorecc")) + return 0; + + return qcom_cc_probe(pdev, &audio_core_cc_shikra_desc); +} + +static struct platform_driver audio_core_cc_shikra_driver = { + .probe = audio_core_cc_shikra_probe, + .driver = { + .name = "audiocorecc-shikra", + .of_match_table = audio_core_cc_shikra_match_table, + }, +}; + +module_platform_driver(audio_core_cc_shikra_driver); + +MODULE_DESCRIPTION("QTI AUDIOCORECC Shikra Driver"); +MODULE_LICENSE("GPL"); From 8b72500d7de7c7931331cfc9e5e9f3234325e90d Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Fri, 15 May 2026 15:19:21 +0530 Subject: [PATCH 0712/1058] soc: qcom: rpmpd: Reuse sm6125 power domains for shikra Shikra shares the same power domain topology as sm6125. Remove the dedicated shikra_rpmpds[] and update shikra_desc to reuse sm6125_rpmpds[] with RPM_SMD_LEVEL_TURBO_NO_CPR. Signed-off-by: Rakesh Kota --- drivers/pmdomain/qcom/rpmpd.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c index 335185830cf38..5f55fc791131a 100644 --- a/drivers/pmdomain/qcom/rpmpd.c +++ b/drivers/pmdomain/qcom/rpmpd.c @@ -863,21 +863,6 @@ static const struct rpmpd_desc sdm660_desc = { .max_state = RPM_SMD_LEVEL_TURBO, }; -static struct rpmpd *shikra_rpmpds[] = { - [RPMPD_VDDCX] = &cx_rwcx0_lvl, - [RPMPD_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [RPMPD_VDDCX_VFL] = &cx_rwcx0_vfl, - [RPMPD_VDDMX] = &mx_rwmx0_lvl, - [RPMPD_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [RPMPD_VDDMX_VFL] = &mx_rwmx0_vfl, -}; - -static const struct rpmpd_desc shikra_desc = { - .rpmpds = shikra_rpmpds, - .num_pds = ARRAY_SIZE(shikra_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, -}; - static struct rpmpd *sm6115_rpmpds[] = { [SM6115_VDDCX] = &cx_rwcx0_lvl, [SM6115_VDDCX_AO] = &cx_rwcx0_lvl_ao, From ede36111befe67173d15174dceed6147a24242ee Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 15 May 2026 14:37:22 +0530 Subject: [PATCH 0713/1058] soc: qcom: pd-mapper: Add shikra PD support for CQM/CQS/IQS All Shikra SoC variants (CQM, CQS, IQS) share the same protection domain requirements: mpss_wlan_pd only. audio_pd is not required on any of these variants. Introduce shikra_cqm_domains with mpss_wlan_pd and wire all three compatibles (qcom,shikra-cqm, qcom,shikra-cqs, qcom,shikra-iqs) to it. Signed-off-by: Anurag Pateriya --- drivers/soc/qcom/qcom_pd_mapper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index b99718e25f2fc..fec4eafeb4ad0 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -463,6 +463,11 @@ static const struct qcom_pdm_domain_data *sc8280xp_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *shikra_cqm_domains[] = { + &mpss_wlan_pd, + NULL, +}; + /* Unlike SDM660, SDM630/636 lack CDSP */ static const struct qcom_pdm_domain_data *sdm630_domains[] = { &adsp_audio_pd, @@ -607,6 +612,9 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, + { .compatible = "qcom,shikra-cqm", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-cqs", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-iqs", .data = shikra_cqm_domains, }, { .compatible = "qcom,sdm630", .data = sdm630_domains, }, { .compatible = "qcom,sdm636", .data = sdm630_domains, }, { .compatible = "qcom,sda660", .data = sdm660_domains, }, From 777101cfdb65adc07195e6a3e8d6fad2b6add7d1 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 20 May 2026 11:18:36 +0530 Subject: [PATCH 0714/1058] soc: qcom: pd-mapper: Fix shikra compatible strings to use -som suffix The Shikra SoC board compatibles use a `-som` suffix (qcom,shikra-cqm-som, qcom,shikra-cqs-som, qcom,shikra-iqs-som). Update the pd-mapper entries added in the previous commit to match. Fixes: 3aa65ff0ed32 ("soc: qcom: pd-mapper: Add shikra PD support for CQM/CQS/IQS") Co-Authored-By: Claude Sonnet 4.6 (1M context) Signed-off-by: Anurag Pateriya --- drivers/soc/qcom/qcom_pd_mapper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index fec4eafeb4ad0..db6c29fe852ac 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -612,9 +612,9 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, - { .compatible = "qcom,shikra-cqm", .data = shikra_cqm_domains, }, - { .compatible = "qcom,shikra-cqs", .data = shikra_cqm_domains, }, - { .compatible = "qcom,shikra-iqs", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-cqm-som", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-cqs-som", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-iqs-som", .data = shikra_cqm_domains, }, { .compatible = "qcom,sdm630", .data = sdm630_domains, }, { .compatible = "qcom,sdm636", .data = sdm630_domains, }, { .compatible = "qcom,sda660", .data = sdm660_domains, }, From ce00aa9935becd82e855307bb84e089a1dd405c0 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Wed, 20 May 2026 18:08:05 +0530 Subject: [PATCH 0715/1058] dt-bindings: regulator: qcom,usb-vbus-regulator: fix allOf schema Consolidate $ref and if/then blocks under a single allOf to ensure all schema constraints are correctly enforced. Signed-off-by: Rakesh Kota --- .../regulator/qcom,usb-vbus-regulator.yaml | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index d34b378517378..024b34d0eb1a6 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -21,9 +21,6 @@ description: | voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V and 5.0 V. -allOf: - - $ref: regulator.yaml# - properties: compatible: oneOf: @@ -41,29 +38,31 @@ properties: maxItems: 1 description: VBUS output base address -if: - properties: - compatible: - contains: - enum: - - qcom,pm8150b-vbus-reg - - qcom,pm6150-vbus-reg - - qcom,pm7250b-vbus-reg - - qcom,pmi632-vbus-reg -then: - required: - - regulator-min-microamp - - regulator-max-microamp +allOf: + - $ref: regulator.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8150b-vbus-reg + - qcom,pm6150-vbus-reg + - qcom,pm7250b-vbus-reg + - qcom,pmi632-vbus-reg + then: + required: + - regulator-min-microamp + - regulator-max-microamp -if: - properties: - compatible: - contains: - const: qcom,pm4125-vbus-reg -then: - required: - - regulator-min-microvolt - - regulator-max-microvolt + - if: + properties: + compatible: + contains: + const: qcom,pm4125-vbus-reg + then: + required: + - regulator-min-microvolt + - regulator-max-microvolt required: - compatible @@ -89,7 +88,7 @@ examples: #address-cells = <1>; #size-cells = <0>; - usb-vbus-regulator@5000 { + usb-vbus-regulator@1100 { compatible = "qcom,pm4125-vbus-reg"; reg = <0x1100>; regulator-min-microvolt = <4250000>; From 2c7ab0d6dd01d10b94763ff5c60cd41b9d125bae Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 20 May 2026 15:53:31 +0530 Subject: [PATCH 0716/1058] dt-bindings: interconnect: qcom-bwmon: Add Shikra cpu-bwmon compatible Add the Qualcomm Shikra SoC compatible string for the CPU-to-DDR bandwidth monitor. Shikra has a BWMONv5 for CPU. Signed-off-by: Sayantan Chakraborty Signed-off-by: Komal Bajaj --- .../devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index ff64225e82817..8f6c937e44cef 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -52,6 +52,7 @@ properties: - qcom,sa8775p-llcc-bwmon - qcom,sc7180-llcc-bwmon - qcom,sc8280xp-llcc-bwmon + - qcom,shikra-cpu-bwmon - qcom,sm6350-cpu-bwmon - qcom,sm8250-llcc-bwmon - qcom,sm8550-llcc-bwmon From c5de0a4fc4679d0221e1a5052ed1c5268dad346f Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 20 May 2026 18:34:19 +0530 Subject: [PATCH 0717/1058] dt-bindings: interconnect: qcom,shikra-epss-l3: Add EPSS L3 DT binding Document the EPSS L3 interconnect provider binding for Qualcomm Shikra SoC. The Shikra EPSS L3 block is similar to existing Qualcomm EPSS/OSM L3 providers, but supports only up to 12 frequency lookup table entries. Introduce Shikra specific bindings to represent this constrained EPSS variant. Signed-off-by: Raviteja Laggyshetty --- .../interconnect/qcom,shikra-epss-l3.yaml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml diff --git a/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml new file mode 100644 index 0000000000000..9cb68a90fa5e1 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,shikra-epss-l3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Operating State Manager (OSM) L3 Shikra Interconnect Provider + +maintainers: + - Raviteja Laggyshetty + +description: + L3 cache bandwidth requirements on Qualcomm SoCs is serviced by the OSM. + The OSM L3 interconnect provider aggregates the L3 bandwidth requests + from CPU/GPU and relays it to the OSM. + +properties: + compatible: + enum: + - qcom,shikra-epss-l3 + + reg: + maxItems: 1 + + clocks: + items: + - description: xo clock + - description: alternate clock + + clock-names: + items: + - const: xo + - const: alternate + + '#interconnect-cells': + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#interconnect-cells' + +additionalProperties: false + +examples: + - | + + #define GPLL0 165 + #define RPMH_CXO_CLK 0 + + epss_l3: interconnect@fd90000 { + compatible = "qcom,shikra-epss-l3"; + reg = <0xfd90000 0x1000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #interconnect-cells = <1>; + }; From 5bebb25dc5b8405fc6fe055a1a6130a55029481f Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 20 May 2026 18:56:15 +0530 Subject: [PATCH 0718/1058] interconnect: qcom: Add EPSS L3 scaling support for Shikra SoC Add Epoch Subsystem (EPSS) L3 interconnect provider support on Qualcomm Shikra SoC. The EPSS L3 block on Shikra SoC is similar to existing Qualcomm EPSS/OSM L3 providers, but supports only up to 12 frequency lookup table entries. Reading beyond the supported LUT entries can expose incorrect frequencies. Add shikra-specifc EPSS descriptor shikra_epss_l3_perf_state that reuses existing EPSS configuration with appropriate LUT entries limit. Signed-off-by: Raviteja Laggyshetty --- drivers/interconnect/qcom/osm-l3.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index b33f00da1880d..ecad636b53e06 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -60,6 +60,7 @@ struct qcom_osm_l3_desc { unsigned int lut_row_size; unsigned int reg_freq_lut; unsigned int reg_perf_state; + unsigned int lut_max_entries; }; #define DEFINE_QNODE(_name, _buswidth) \ @@ -90,6 +91,7 @@ static const struct qcom_osm_l3_desc osm_l3 = { .lut_row_size = OSM_LUT_ROW_SIZE, .reg_freq_lut = OSM_REG_FREQ_LUT, .reg_perf_state = OSM_REG_PERF_STATE, + .lut_max_entries = LUT_MAX_ENTRIES, }; static const struct qcom_osm_l3_desc epss_l3_perf_state = { @@ -98,6 +100,16 @@ static const struct qcom_osm_l3_desc epss_l3_perf_state = { .lut_row_size = EPSS_LUT_ROW_SIZE, .reg_freq_lut = EPSS_REG_FREQ_LUT, .reg_perf_state = EPSS_REG_PERF_STATE, + .lut_max_entries = LUT_MAX_ENTRIES, +}; + +static const struct qcom_osm_l3_desc shikra_epss_l3_perf_state = { + .nodes = epss_l3_nodes, + .num_nodes = ARRAY_SIZE(epss_l3_nodes), + .lut_row_size = EPSS_LUT_ROW_SIZE, + .reg_freq_lut = EPSS_REG_FREQ_LUT, + .reg_perf_state = EPSS_REG_PERF_STATE, + .lut_max_entries = 12, }; static const struct qcom_osm_l3_desc epss_l3_l3_vote = { @@ -106,6 +118,7 @@ static const struct qcom_osm_l3_desc epss_l3_l3_vote = { .lut_row_size = EPSS_LUT_ROW_SIZE, .reg_freq_lut = EPSS_REG_FREQ_LUT, .reg_perf_state = EPSS_REG_L3_VOTE, + .lut_max_entries = LUT_MAX_ENTRIES, }; static int qcom_osm_l3_set(struct icc_node *src, struct icc_node *dst) @@ -189,7 +202,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) qp->reg_perf_state = desc->reg_perf_state; - for (i = 0; i < LUT_MAX_ENTRIES; i++) { + for (i = 0; i < desc->lut_max_entries; i++) { info = readl_relaxed(qp->base + desc->reg_freq_lut + i * desc->lut_row_size); src = FIELD_GET(LUT_SRC, info); @@ -272,6 +285,7 @@ static const struct of_device_id osm_l3_of_match[] = { { .compatible = "qcom,sc7180-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sc7280-epss-l3", .data = &epss_l3_perf_state }, { .compatible = "qcom,sdm845-osm-l3", .data = &osm_l3 }, + { .compatible = "qcom,shikra-epss-l3", .data = &shikra_epss_l3_perf_state }, { .compatible = "qcom,sm8150-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sc8180x-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sm8250-epss-l3", .data = &epss_l3_perf_state }, From e4409bb46fcb4d6d24d5961e6ec6a65981989284 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 12 May 2026 12:03:19 +0530 Subject: [PATCH 0719/1058] dt-bindings: media: qcom: Add Shikra CAMSS compatible Shikra uses the same CAMSS IP as QCM2290. Extend the existing qcom,qcm2290-camss binding to add the qcom,shikra-camss compatible string. Co-developed-by: Vikram Sharma Signed-off-by: Vikram Sharma Signed-off-by: Nihal Kumar Gupta --- .../devicetree/bindings/media/qcom,qcm2290-camss.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml index 391d0f6f67ef5..7b1469d6a1601 100644 --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml @@ -8,13 +8,16 @@ title: Qualcomm QCM2290 Camera Subsystem (CAMSS) maintainers: - Loic Poulain + - Nihal Kumar Gupta description: The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. properties: compatible: - const: qcom,qcm2290-camss + enum: + - qcom,qcm2290-camss + - qcom,shikra-camss reg: maxItems: 9 @@ -76,6 +79,7 @@ properties: - const: sf_mnoc iommus: + minItems: 1 maxItems: 4 power-domains: From 7b9baa4df1b2c93fe4298f0d1b7391105c73f5a4 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Fri, 15 May 2026 19:16:22 +0530 Subject: [PATCH 0720/1058] media: qcom: camss: add support for QCM2390 camss Add CAMSS driver support for Shikra SoC. Add high level resource definitions for 2 CSIPHY, 2 CSID and 2 VFE instances along with the interconnect bandwidth votes for AHB, HF and SF MNOC paths. Co-developed-by: Vikram Sharma Signed-off-by: Vikram Sharma Signed-off-by: Prashant Shrotriya --- .../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 2 ++ drivers/media/platform/qcom/camss/camss-vfe.c | 1 + drivers/media/platform/qcom/camss/camss.c | 13 +++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 4 files changed, 17 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index dac8d2ecf7995..62208f5c4f17b 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1130,6 +1130,7 @@ static bool csiphy_is_gen2(u32 version) switch (version) { case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -1222,6 +1223,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: regs->lane_regs = &lane_regs_qcm2290[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 319d191589884..b152f8d48e003 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -342,6 +342,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, break; case CAMSS_660: case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2123f6388e3d7..f67ecff53f15b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5565,6 +5565,18 @@ static const struct camss_resources qcm2290_resources = { .vfe_num = ARRAY_SIZE(vfe_res_2290), }; +static const struct camss_resources qcm2390_resources = { + .version = CAMSS_2390, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", @@ -5752,6 +5764,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm670-camss", .data = &sdm670_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, + { .compatible = "qcom,shikra-camss", .data = &qcm2390_resources }, { .compatible = "qcom,sm6150-camss", .data = &sm6150_resources }, { .compatible = "qcom,sm6350-camss", .data = &sm6350_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 93d691c8ac63b..8ba8a38113dfc 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -82,6 +82,7 @@ enum pm_domain { enum camss_version { CAMSS_660, CAMSS_2290, + CAMSS_2390, CAMSS_6150, CAMSS_6350, CAMSS_7280, From b1e033dc1bfc9f75859c294874344c66251ce4f0 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 19 May 2026 16:07:59 +0530 Subject: [PATCH 0721/1058] soc: qcom: smsm: Increase default num_hosts to 5 for Shikra SMEM_SMSM_SIZE_INFO (id 419) is not populated by the boot firmware on Shikra. The SMSM driver falls back to SMSM_DEFAULT_NUM_HOSTS when this segment is absent, which causes SMEM_SMSM_CPU_INTR_MASK (id 333) to be allocated with the wrong size. The upstream default of 3 allocates 8*3*4 = 96 bytes. Shikra modem firmware expects 8*5*4 = 160 bytes, matching the num_hosts=5 used by the downstream kernel. The size mismatch causes the modem to crash on boot with "smsm.c: Bad pointer from smem_alloc". Increasing the host count only results in a larger allocation, so this change is safe for existing platforms. Increase the default to 5 to match the modem firmware expectation. Signed-off-by: Vishnu Santhosh --- drivers/soc/qcom/smsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 021e9d1f61dc5..7d1823ab4198b 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -54,7 +54,7 @@ * Default sizes, in case SMEM_SMSM_SIZE_INFO is not found. */ #define SMSM_DEFAULT_NUM_ENTRIES 8 -#define SMSM_DEFAULT_NUM_HOSTS 3 +#define SMSM_DEFAULT_NUM_HOSTS 5 struct smsm_entry; struct smsm_host; From 9925bf299b4c119d1b1af4a2366ec57c79a408f3 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Wed, 20 May 2026 10:26:48 +0530 Subject: [PATCH 0722/1058] dmaengine: qcom: bam_dma: Defer IRQ trigger type to device tree The driver hardcodes IRQF_TRIGGER_HIGH when registering the BAM interrupt, which overrides the trigger type specified in the device tree. This is incorrect for platforms like Shikra where the A2 BAM requires edge-triggered interrupts. Use IRQF_TRIGGER_NONE instead, which causes the kernel to use the trigger type already configured by platform_get_irq() when it parsed the device tree interrupts property. This makes the driver platform-agnostic. Signed-off-by: Vishnu Santhosh --- drivers/dma/qcom/bam_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 1bb26af0405f3..b24d3f557c830 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1333,7 +1333,7 @@ static int bam_dma_probe(struct platform_device *pdev) bam_channel_init(bdev, &bdev->channels[i], i); ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq, - IRQF_TRIGGER_HIGH, "bam_dma", bdev); + IRQF_TRIGGER_NONE, "bam_dma", bdev); if (ret) goto err_bam_channel_exit; From ede784ff178ef5993b55be66ab7ccf8b7b95a718 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 19 May 2026 16:37:43 +0530 Subject: [PATCH 0723/1058] arm64: defconfig: Enable Qualcomm BAM-DMUX WWAN driver This driver provides access to modem data channels on platforms using the A2 BAM hardware, including Shikra. Signed-off-by: Vishnu Santhosh --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c02157e9c9d4b..7d4b24b378a5d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -521,6 +521,7 @@ CONFIG_WLCORE_SDIO=m CONFIG_WWAN=m CONFIG_MHI_WWAN_CTRL=m CONFIG_MHI_WWAN_MBIM=m +CONFIG_QCOM_BAM_DMUX=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_ADC=m CONFIG_KEYBOARD_GPIO=y From 2b9dab37a990fee23ba02e27fa2cc23d468c3583 Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Fri, 8 May 2026 21:40:08 +0800 Subject: [PATCH 0724/1058] FROMLIST: dt-bindings: bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: - LT9611C: supports 1-port mipi dsi to hdmi 1.4 - LT9611EX: supports 2-port mipi dsi to hdmi 1.4 - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0 Link : https://lore.kernel.org/lkml/20260508134009.4582-3-syyang@lontium.com/ Signed-off-by: Sunyun Yang Signed-off-by: Mohit Dsor --- .../bindings/display/bridge/lontium,lt9611.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml index 429a06057ae85..e0821a63d9d74 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -4,19 +4,23 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9611(UXC) 2 Port MIPI to HDMI Bridge +title: Lontium LT9611(UXC/C/EX/UXD) 2 Port MIPI DSI to HDMI Bridge maintainers: - Vinod Koul description: | - The LT9611 and LT9611UXC are bridge devices which convert DSI to HDMI + The LT9611、LT9611UXC、LT9611C、LT9611EX and LT9611UXD + are bridge devices which convert DSI to HDMI properties: compatible: enum: - lontium,lt9611 + - lontium,lt9611c + - lontium,lt9611ex - lontium,lt9611uxc + - lontium,lt9611uxd reg: maxItems: 1 From 176b6da58b0ff4cbec21685bb884106e6ed0016b Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Fri, 8 May 2026 21:40:09 +0800 Subject: [PATCH 0725/1058] FROMLIST: drm/bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: - LT9611C: supports 1-port mipi dsi to hdmi 1.4 - LT9611EX: supports 2-port mipi dsi to hdmi 1.4 - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0 Link : https://lore.kernel.org/lkml/20260508134009.4582-3-syyang@lontium.com/ Signed-off-by: Sunyun Yang Signed-off-by: Mohit Dsor Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/Kconfig | 18 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/lontium-lt9611c.c | 1241 ++++++++++++++++++++++ 3 files changed, 1260 insertions(+) create mode 100644 drivers/gpu/drm/bridge/lontium-lt9611c.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 4a57d49b4c6d3..b8959b8e2ad05 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -177,6 +177,24 @@ config DRM_LONTIUM_LT9611 HDMI signals Please say Y if you have such hardware. +config DRM_LONTIUM_LT9611C + tristate "Lontium LT9611C DSI/HDMI bridge" + select SND_SOC_HDMI_CODEC if SND_SOC + depends on OF + select CRC8 + select FW_LOADER + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select REGMAP_I2C + help + Driver for Lontium DSI to HDMI bridge + chip driver that converts dual DSI and I2S to + HDMI signals + Please say Y if you have such hardware. + config DRM_LONTIUM_LT9611UXC tristate "Lontium LT9611UXC DSI/HDMI bridge" select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 15cc821d85b7e..f322f3f89f6bf 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o +obj-$(CONFIG_DRM_LONTIUM_LT9611C) += lontium-lt9611c.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o obj-$(CONFIG_DRM_LONTIUM_LT8713SX) += lontium-lt8713sx.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c new file mode 100644 index 0000000000000..cb584855fd8f0 --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -0,0 +1,1241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 Lontium Semiconductor, Inc. + */ + +#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 + +#define FW_SIZE (64 * 1024) +#define LT_PAGE_SIZE 256 +#define FW_FILE "Lontium/lt9611c_fw.bin" +#define LT9611C_CRC_POLYNOMIAL 0x31 +#define LT9611C_PAGE_CONTROL 0xff + +enum lt9611_chip_type { + CHIP_LT9611C = 0, + CHIP_LT9611EX, + CHIP_LT9611UXD, +}; + +struct lt9611c { + struct device *dev; + struct i2c_client *client; + struct drm_bridge bridge; + struct regmap *regmap; + /* Protects all accesses to registers by stopping the on-chip MCU */ + struct mutex ocm_lock; + struct work_struct work; + struct device_node *dsi0_node; + struct device_node *dsi1_node; + struct mipi_dsi_device *dsi0; + struct mipi_dsi_device *dsi1; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[2]; + int fw_version; + /* Chip variant: C/EX/UXD */ + enum lt9611_chip_type chip_type; + /* HDMI cable connection status */ + bool hdmi_connected; +}; + +DECLARE_CRC8_TABLE(lt9611c_crc8_table); + +static const struct regmap_range_cfg lt9611c_ranges[] = { + { + .name = "register_range", + .range_min = 0, + .range_max = 0xfe9c, + .selector_reg = LT9611C_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config lt9611c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xfe9c, + .ranges = lt9611c_ranges, + .num_ranges = ARRAY_SIZE(lt9611c_ranges), +}; + +static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, + unsigned int param_count, u8 *return_buffer, + unsigned int return_count) +{ + int ret; + unsigned int i; + unsigned int temp; + unsigned int max_params = 0xe0dd - 0xe0b0 + 1; + + regmap_write(lt9611c->regmap, 0xe0de, 0x01); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x01, 1000, 100 * 1000); + if (ret) + return -ETIMEDOUT; + + for (i = 0; i < param_count && i < max_params; i++) + regmap_write(lt9611c->regmap, 0xe0b0 + i, params[i]); + + regmap_write(lt9611c->regmap, 0xe0de, 0x02); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x02, 1000, 100 * 1000); + if (ret) + return -ETIMEDOUT; + + return regmap_bulk_read(lt9611c->regmap, 0xe085, return_buffer, + return_count); +} + +static void lt9611c_config_parameters(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write_paras[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe103, 0x3f), /*fifo rst*/ + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0xc1), + REG_SEQ0(0xe058, 0x00), + REG_SEQ0(0xe059, 0x50), + REG_SEQ0(0xe05a, 0x10), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write_paras, ARRAY_SIZE(seq_write_paras)); +} + +static void lt9611c_wren(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x04); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_wrdi(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x08); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_erase_op(struct lt9611c *lt9611c, u32 addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe05a, 0x04), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x01), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void read_flash_reg_status(struct lt9611c *lt9611c, unsigned int *status) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe103, 0x3f), + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0x40), + REG_SEQ0(0xe056, 0x05), + REG_SEQ0(0xe055, 0x25), + REG_SEQ0(0xe055, 0x01), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); + + regmap_read(lt9611c->regmap, 0xe05f, status); +} + +static void lt9611c_crc_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0x00), + REG_SEQ0(0xe055, 0xc0), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_data_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0xff), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_sram_to_flash(struct lt9611c *lt9611c, size_t addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x30), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_block_erase(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int i; + unsigned int block_num; + unsigned int flash_status = 0; + u32 flash_addr = 0; + + for (block_num = 0; block_num < 2; block_num++) { + flash_addr = (block_num * 0x008000); + lt9611c_erase_op(lt9611c, flash_addr); + msleep(100); + i = 0; + while (1) { + read_flash_reg_status(lt9611c, &flash_status); + if ((flash_status & 0x01) == 0) + break; + + if (i > 50) + break; + + i++; + msleep(50); + } + } + + dev_dbg(dev, "erase flash done.\n"); +} + +static int lt9611c_write_data(struct lt9611c *lt9611c, const struct firmware *fw, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + unsigned int page = 0, num = 0, i = 0; + size_t size, index; + const u8 *data; + u8 value; + + data = fw->data; + size = fw->size; + page = (size + LT_PAGE_SIZE - 1) / LT_PAGE_SIZE; + if (page * LT_PAGE_SIZE > FW_SIZE) { + dev_err(dev, "firmware size out of range\n"); + return -EINVAL; + } + + dev_dbg(dev, "%u pages, total size %zu byte\n", page, size); + + for (num = 0; num < page; num++) { + lt9611c_data_to_sram(lt9611c); + + for (i = 0; i < LT_PAGE_SIZE; i++) { + index = num * LT_PAGE_SIZE + i; + value = (index < size) ? data[index] : 0xff; + + ret = regmap_write(lt9611c->regmap, 0xe059, value); + if (ret < 0) { + dev_err(dev, "write error at page %u, index %u\n", num, i); + return ret; + } + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + + addr += LT_PAGE_SIZE; + } + + lt9611c_wrdi(lt9611c); + + return 0; +} + +static int lt9611c_write_crc(struct lt9611c *lt9611c, u8 fw_crc, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c_crc_to_sram(lt9611c); + ret = regmap_write(lt9611c->regmap, 0xe059, fw_crc); + if (ret < 0) { + dev_err(dev, "failed to write crc\n"); + return ret; + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + lt9611c_wrdi(lt9611c); + + dev_dbg(dev, "crc 0x%02x written to flash at addr 0x%zx\n", fw_crc, addr); + + return 0; +} + +static void lt9611c_reset(struct lt9611c *lt9611c) +{ + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(400); + + dev_dbg(lt9611c->dev, "lt9611c reset"); +} + +static int lt9611c_upgrade_result(struct lt9611c *lt9611c, u8 fw_crc) +{ + struct device *dev = lt9611c->dev; + unsigned int crc_result; + + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + regmap_read(lt9611c->regmap, 0xe021, &crc_result); + + if (crc_result != fw_crc) { + dev_err(dev, "lt9611c fw upgrade failed, expected crc=0x%02x, read crc=0x%02x\n", + fw_crc, crc_result); + return -1; + } + + dev_dbg(dev, "lt9611c firmware upgrade success, crc=0x%02x\n", crc_result); + return 0; +} + +static int lt9611c_firmware_upgrade(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + const struct firmware *fw; + u8 *buffer; + size_t total_size = FW_SIZE - 1; + u8 fw_crc; + int ret; + + /* 1. load firmware */ + ret = request_firmware(&fw, FW_FILE, dev); + if (ret) + return dev_err_probe(dev, ret, "failed to load '%s'\n", FW_FILE); + + /* 2. check size */ + if (fw->size > total_size) { + dev_err(dev, "firmware too large (%zu > %zu)\n", fw->size, total_size); + ret = -EINVAL; + goto out_release_fw; + } + dev_dbg(dev, "firmware size: %zu bytes\n", fw->size); + + /* 3. calculate crc8 */ + buffer = kzalloc(total_size, GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto out_release_fw; + } + + memset(buffer, 0xff, total_size); + memcpy(buffer, fw->data, fw->size); + + fw_crc = crc8(lt9611c_crc8_table, buffer, total_size, 0); + kfree(buffer); + + dev_dbg(dev, "firmware crc: 0x%02x\n", fw_crc); + dev_dbg(dev, "starting firmware upgrade, size: %zu bytes\n", fw->size); + + /* 4. firmware upgrade */ + lt9611c_config_parameters(lt9611c); + lt9611c_block_erase(lt9611c); + + ret = lt9611c_write_data(lt9611c, fw, 0); + if (ret < 0) { + dev_err(dev, "failed to write firmware data\n"); + goto out_release_fw; + } + + ret = lt9611c_write_crc(lt9611c, fw_crc, FW_SIZE - 1); + if (ret < 0) { + dev_err(dev, "failed to write firmware crc\n"); + goto out_release_fw; + } + + /* 5. check upgrade of result */ + lt9611c_reset(lt9611c); + ret = lt9611c_upgrade_result(lt9611c, fw_crc); + +out_release_fw: + release_firmware(fw); + return ret; +} + +static struct lt9611c *bridge_to_lt9611c(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9611c, bridge); +} + +/*read only*/ +static const struct lt9611c *bridge_to_lt9611c_const(const struct drm_bridge *bridge) +{ + return container_of(bridge, const struct lt9611c, bridge); +} + +static void lt9611c_lock(struct lt9611c *lt9611c) +{ + mutex_lock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); +} + +static void lt9611c_unlock(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + mutex_unlock(<9611c->ocm_lock); +} + +static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) +{ + struct lt9611c *lt9611c = dev_id; + struct device *dev = lt9611c->dev; + int ret; + unsigned int irq_status; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); + if (ret) { + dev_err(dev, "failed to read irq status: %d\n", ret); + return IRQ_HANDLED; + } + + if (!(irq_status & BIT(0))) + return IRQ_HANDLED; + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) { + dev_err(dev, "failed to read HPD status\n"); + } else { + lt9611c->hdmi_connected = (data[4] == 0x02); + dev_dbg(dev, "HDMI %s\n", lt9611c->hdmi_connected ? "connected" : "disconnected"); + } + + /*Clear interrupt: hardware requires two writes with delay*/ + regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); + usleep_range(10000, 12000); + regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); + + schedule_work(<9611c->work); + + return IRQ_HANDLED; +} + +static void lt9611c_hpd_work(struct work_struct *work) +{ + struct lt9611c *lt9611c = container_of(work, struct lt9611c, work); + bool connected; + + mutex_lock(<9611c->ocm_lock); + connected = lt9611c->hdmi_connected; + mutex_unlock(<9611c->ocm_lock); + + drm_bridge_hpd_notify(<9611c->bridge, + connected ? connector_status_connected : + connector_status_disconnected); +} + +static int lt9611c_regulator_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c->supplies[0].supply = "vcc"; + lt9611c->supplies[1].supply = "vdd"; + + ret = devm_regulator_bulk_get(dev, 2, lt9611c->supplies); + + return ret; +} + +static struct mipi_dsi_device *lt9611c_attach_dsi(struct lt9611c *lt9611c, + struct device_node *dsi_node) +{ + const struct mipi_dsi_device_info info = { "lt9611c", 0, NULL }; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + struct device *dev = lt9611c->dev; + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n")); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE; + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) + return ERR_PTR(dev_err_probe(dev, ret, "failed to attach dsi to host\n")); + + return dsi; +} + +static int lt9611c_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, + enum drm_bridge_attach_flags flags) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_bridge_attach(encoder, lt9611c->bridge.next_bridge, bridge, flags); +} + +static enum drm_mode_status +lt9611c_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + const struct lt9611c *lt9611c = bridge_to_lt9611c_const(bridge); + + if (lt9611c->chip_type == CHIP_LT9611UXD) { + if (tmds_rate > 600000000) + return MODE_CLOCK_HIGH; + + } else { + if (tmds_rate > 340000000) + return MODE_CLOCK_HIGH; + } + + if (tmds_rate < 25000000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static void lt9611c_video_setup(struct lt9611c *lt9611c, + const struct drm_display_mode *mode) +{ + struct device *dev = lt9611c->dev; + int ret; + u32 h_total, hactive, hsync_len, hfront_porch, hback_porch; + u32 v_total, vactive, vsync_len, vfront_porch, vback_porch; + u8 timing_set_cmd[26] = {0x57, 0x4d, 0x33, 0x3a}; + u8 return_param[3]; + u8 framerate; + u8 vic = 0x00; + + guard(mutex)(<9611c->ocm_lock); + h_total = mode->htotal; + hactive = mode->hdisplay; + hsync_len = mode->hsync_end - mode->hsync_start; + hfront_porch = mode->hsync_start - mode->hdisplay; + hback_porch = mode->htotal - mode->hsync_end; + + v_total = mode->vtotal; + vactive = mode->vdisplay; + vsync_len = mode->vsync_end - mode->vsync_start; + vfront_porch = mode->vsync_start - mode->vdisplay; + vback_porch = mode->vtotal - mode->vsync_end; + framerate = drm_mode_vrefresh(mode); + vic = drm_match_cea_mode(mode); + + dev_dbg(dev, "hactive=%d, vactive=%d\n", hactive, vactive); + dev_dbg(dev, "framerate=%d\n", framerate); + dev_dbg(dev, "vic = 0x%02x\n", vic); + + timing_set_cmd[4] = (h_total >> 8) & 0xff; + timing_set_cmd[5] = h_total & 0xff; + timing_set_cmd[6] = (hactive >> 8) & 0xff; + timing_set_cmd[7] = hactive & 0xff; + timing_set_cmd[8] = (hfront_porch >> 8) & 0xff; + timing_set_cmd[9] = hfront_porch & 0xff; + timing_set_cmd[10] = (hsync_len >> 8) & 0xff; + timing_set_cmd[11] = hsync_len & 0xff; + timing_set_cmd[12] = (hback_porch >> 8) & 0xff; + timing_set_cmd[13] = hback_porch & 0xff; + timing_set_cmd[14] = (v_total >> 8) & 0xff; + timing_set_cmd[15] = v_total & 0xff; + timing_set_cmd[16] = (vactive >> 8) & 0xff; + timing_set_cmd[17] = vactive & 0xFF; + timing_set_cmd[18] = (vfront_porch >> 8) & 0xff; + timing_set_cmd[19] = vfront_porch & 0xff; + timing_set_cmd[20] = (vsync_len >> 8) & 0xff; + timing_set_cmd[21] = vsync_len & 0xff; + timing_set_cmd[22] = (vback_porch >> 8) & 0xff; + timing_set_cmd[23] = vback_porch & 0xff; + timing_set_cmd[24] = framerate; + timing_set_cmd[25] = vic; + + ret = lt9611c_read_write_flow(lt9611c, + timing_set_cmd, ARRAY_SIZE(timing_set_cmd), + return_param, ARRAY_SIZE(return_param)); + if (ret) + dev_err(dev, "video set failed\n"); +} + +static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + lt9611c_reset(lt9611c); +} + +static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *mode; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + mode = &crtc_state->adjusted_mode; + + lt9611c_video_setup(lt9611c, mode); +} + +static void lt9611c_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); +} + +static enum drm_connector_status +lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct device *dev = lt9611c->dev; + int ret; + bool connected = false; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) + dev_err(dev, "failed to read HPD status (err=%d)\n", ret); + else + connected = (data[4] == 0x02); + + lt9611c->hdmi_connected = connected; + + return connected ? connector_status_connected : + connector_status_disconnected; +} + +static int lt9611c_get_edid_block(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct lt9611c *lt9611c = data; + struct device *dev = lt9611c->dev; + u8 cmd[5] = {0x52, 0x48, 0x33, 0x3a, 0x00}; + u8 packet[37]; + int ret, i, offset = 0; + + if (len != 128) + return -EINVAL; + guard(mutex)(<9611c->ocm_lock); + + for (i = 0; i < 4; i++) { + cmd[4] = block * 4 + i; + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + packet, ARRAY_SIZE(packet)); + if (ret) { + dev_err(dev, "Failed to read EDID block %u packet %d\n", + block, i); + return ret; + } + memcpy(buf + offset, &packet[5], 32); + offset += 32; + } + + return 0; +} + +static const struct drm_edid *lt9611c_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_edid_read_custom(connector, lt9611c_get_edid_block, lt9611c); +} + +static int lt9611c_hdmi_write_avi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x01;/*write avi*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x01}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x02;/*write audio*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_audio_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x02}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 audio_cmd[6] = {0x57, 0x48, 0x36, 0x3a}; + u8 data[5]; + int ret; + + if (hparms->sample_width == 32) + return -EINVAL; + + switch (fmt->fmt) { + case HDMI_I2S: + audio_cmd[4] = 0x01; + break; + case HDMI_SPDIF: + audio_cmd[4] = 0x02; + break; + default: + return -EINVAL; + } + + audio_cmd[5] = hparms->channels; + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, audio_cmd, sizeof(audio_cmd), + data, sizeof(data)); + if (ret < 0) { + dev_err(lt9611c->dev, "set audio info failed!\n"); + return ret; + } + + return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + &hparms->cea); +} + +static void lt9611c_hdmi_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); +} + +static int lt9611c_hdmi_audio_startup(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + return 0; +} + +static const struct drm_bridge_funcs lt9611c_bridge_funcs = { + .attach = lt9611c_bridge_attach, + .detect = lt9611c_bridge_detect, + .edid_read = lt9611c_bridge_edid_read, + .atomic_pre_enable = lt9611c_bridge_atomic_pre_enable, + .atomic_enable = lt9611c_bridge_atomic_enable, + .atomic_post_disable = lt9611c_bridge_atomic_post_disable, + .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, + + .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, + .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, + .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, + .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, + + .hdmi_audio_startup = lt9611c_hdmi_audio_startup, + .hdmi_audio_prepare = lt9611c_hdmi_audio_prepare, + .hdmi_audio_shutdown = lt9611c_hdmi_audio_shutdown, +}; + +static int lt9611c_parse_dt(struct device *dev, + struct lt9611c *lt9611c) +{ + lt9611c->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); + if (!lt9611c->dsi0_node) + return dev_err_probe(dev, -ENODEV, "failed to get remote node for primary dsi\n"); + + lt9611c->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + + return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); +} + +static int lt9611c_gpio_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + + lt9611c->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(lt9611c->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(lt9611c->reset_gpio), + "failed to acquire reset gpio\n"); + + return 0; +} + +static int lt9611c_read_version(struct lt9611c *lt9611c) +{ + u8 buf[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe080, buf, ARRAY_SIZE(buf)); + if (ret) + return ret; + + return (buf[0] << 8) | buf[1]; +} + +static int lt9611c_read_chipid(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + u8 chipid[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe100, chipid, 2); + if (ret) + return ret; + + if (chipid[0] != 0x23 || chipid[1] != 0x06) { + dev_err(dev, "ChipID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + return -ENODEV; + } + + return 0; +} + +static ssize_t lt9611c_firmware_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + lt9611c_lock(lt9611c); + + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) + dev_err(dev, "upgrade failure\n"); + + lt9611c_unlock(lt9611c); + + return ret < 0 ? ret : len; +} + +static ssize_t lt9611c_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%04x\n", lt9611c->fw_version); +} + +static DEVICE_ATTR_RW(lt9611c_firmware); + +static struct attribute *lt9611c_attrs[] = { + &dev_attr_lt9611c_firmware.attr, + NULL, +}; + +static const struct attribute_group lt9611c_attr_group = { + .attrs = lt9611c_attrs, +}; + +static const struct attribute_group *lt9611c_attr_groups[] = { + <9611c_attr_group, + NULL, +}; + +static int lt9611c_probe(struct i2c_client *client) +{ + const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct lt9611c *lt9611c; + struct device *dev = &client->dev; + bool fw_updated = false; + int ret; + + crc8_populate_msb(lt9611c_crc8_table, LT9611C_CRC_POLYNOMIAL); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return dev_err_probe(dev, -ENODEV, "device doesn't support I2C\n"); + + lt9611c = devm_drm_bridge_alloc(dev, struct lt9611c, bridge, <9611c_bridge_funcs); + if (IS_ERR(lt9611c)) + return dev_err_probe(dev, PTR_ERR(lt9611c), "drm bridge alloc failed.\n"); + + lt9611c->dev = dev; + lt9611c->client = client; + lt9611c->chip_type = id->driver_data; + ret = devm_mutex_init(dev, <9611c->ocm_lock); + if (ret) + return dev_err_probe(dev, ret, "failed to init mutex\n"); + + lt9611c->regmap = devm_regmap_init_i2c(client, <9611c_regmap_config); + if (IS_ERR(lt9611c->regmap)) + return dev_err_probe(dev, PTR_ERR(lt9611c->regmap), "regmap i2c init failed\n"); + + ret = lt9611c_parse_dt(dev, lt9611c); + if (ret) + return dev_err_probe(dev, ret, "failed to parse device tree\n"); + + ret = lt9611c_gpio_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = lt9611c_regulator_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + goto err_of_put; + + lt9611c_reset(lt9611c); + + lt9611c_lock(lt9611c); + + ret = lt9611c_read_chipid(lt9611c); + if (ret < 0) { + dev_err(dev, "failed to read chip id.\n"); + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + +retry: + lt9611c->fw_version = lt9611c_read_version(lt9611c); + if (lt9611c->fw_version < 0) { + dev_err(dev, "failed to read fw version\n"); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + + } else if (lt9611c->fw_version == 0) { + if (!fw_updated) { + fw_updated = true; + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) { + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + + goto retry; + + } else { + dev_err(dev, "fw version 0x%04x, update failed\n", lt9611c->fw_version); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + } + + lt9611c_unlock(lt9611c); + dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); + + INIT_WORK(<9611c->work, lt9611c_hpd_work); + + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + lt9611c_irq_thread_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT | + IRQF_NO_AUTOEN, + "lt9611c", lt9611c); + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto err_disable_regulators; + } + + lt9611c->bridge.of_node = client->dev.of_node; + lt9611c->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO; + lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + + lt9611c->bridge.hdmi_audio_dev = dev; + lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; + lt9611c->bridge.hdmi_audio_dai_port = 2; + + devm_drm_bridge_add(dev, <9611c->bridge); + + /* Attach primary DSI */ + lt9611c->dsi0 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi0_node); + if (IS_ERR(lt9611c->dsi0)) { + ret = PTR_ERR(lt9611c->dsi0); + goto err_remove_bridge; + } + + /* Attach secondary DSI, if specified */ + if (lt9611c->dsi1_node) { + lt9611c->dsi1 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi1_node); + if (IS_ERR(lt9611c->dsi1)) { + ret = PTR_ERR(lt9611c->dsi1); + goto err_remove_bridge; + } + } + + lt9611c->hdmi_connected = false; + i2c_set_clientdata(client, lt9611c); + enable_irq(client->irq); + lt9611c_reset(lt9611c); + + return 0; + +err_remove_bridge: + free_irq(client->irq, lt9611c); + cancel_work_sync(<9611c->work); + drm_bridge_remove(<9611c->bridge); + +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + +err_of_put: + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); + + return ret; +} + +static void lt9611c_remove(struct i2c_client *client) +{ + struct lt9611c *lt9611c = i2c_get_clientdata(client); + + free_irq(client->irq, lt9611c); + cancel_work_sync(<9611c->work); + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); +} + +static int lt9611c_bridge_suspend(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + dev_dbg(lt9611c->dev, "suspend\n"); + disable_irq(lt9611c->client->irq); + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + return ret; + } + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + + return ret; +} + +static int lt9611c_bridge_resume(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + return ret; + } + enable_irq(lt9611c->client->irq); + lt9611c_reset(lt9611c); + dev_dbg(lt9611c->dev, "resume\n"); + + return ret; +} + +static const struct dev_pm_ops lt9611c_bridge_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(lt9611c_bridge_suspend, + lt9611c_bridge_resume) +}; + +static struct i2c_device_id lt9611c_id[] = { + /* chip_type */ + { "lontium,lt9611c", 0 }, + { "lontium,lt9611ex", 1 }, + { "lontium,lt9611uxd", 2 }, + { /* sentinel */ } +}; + +static const struct of_device_id lt9611c_match_table[] = { + { .compatible = "lontium,lt9611c" }, + { .compatible = "lontium,lt9611ex" }, + { .compatible = "lontium,lt9611uxd" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lt9611c_match_table); + +static struct i2c_driver lt9611c_driver = { + .driver = { + .name = "lt9611c", + .of_match_table = lt9611c_match_table, + .pm = <9611c_bridge_pm_ops, + .dev_groups = lt9611c_attr_groups, + }, + .probe = lt9611c_probe, + .remove = lt9611c_remove, + .id_table = lt9611c_id, +}; +module_i2c_driver(lt9611c_driver); + +MODULE_AUTHOR("SunYun Yang "); +MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FW_FILE); + From 428054fe71772f95a784c32f6f5ce1f484a76b66 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:23 +0800 Subject: [PATCH 0726/1058] FROMLIST: drm/msm/dp: remove cached drm_edid from panel The cached drm_edid seems unnecessary here. Use the drm_edid pointer directly in the plug stage instead of caching it. Remove the cached drm_edid and the corresponding oneliner to simplify the code. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-1-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 28 +++++++++----- drivers/gpu/drm/msm/dp/dp_panel.c | 57 +++-------------------------- drivers/gpu/drm/msm/dp/dp_panel.h | 13 ++----- 3 files changed, 27 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index dc6f33809ca5f..bce165bac106b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -269,6 +269,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) const struct drm_display_info *info = &connector->display_info; int rc = 0; u8 dpcd[DP_RECEIVER_CAP_SIZE]; + const struct drm_edid *drm_edid = NULL; rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); if (rc) @@ -276,10 +277,20 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); - rc = msm_dp_panel_read_sink_caps(dp->panel, connector); + rc = msm_dp_panel_read_link_caps(dp->panel, connector); if (rc) goto end; + drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); + drm_edid_connector_update(connector, drm_edid); + + if (!drm_edid) { + DRM_ERROR("panel edid read failed\n"); + /* check edid read fail is due to unplug */ + if (!msm_dp_aux_is_link_connected(dp->aux)) + return -ETIMEDOUT; + } + msm_dp_link_process_request(dp->link); if (!dp->msm_dp_display.is_edp) @@ -291,7 +302,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; dp->audio_supported = info->has_audio; - msm_dp_panel_handle_sink_request(dp->panel); + msm_dp_panel_handle_sink_request(dp->panel, drm_edid); /* * set sink to normal operation mode -- D0 @@ -302,6 +313,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) msm_dp_link_reset_phy_params_vx_px(dp->link); end: + drm_edid_free(drm_edid); return rc; } @@ -453,7 +465,7 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) /* Don't forget modes for eDP */ if (!dp->msm_dp_display.is_edp) - msm_dp_panel_unplugged(dp->panel, dp->msm_dp_display.connector); + drm_edid_connector_update(dp->msm_dp_display.connector, NULL); /* triggered by irq_hdp with sink_count = 0 */ if (dp->link->sink_count == 0) @@ -515,7 +527,6 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); - msm_dp_panel_put(dp->panel); msm_dp_aux_put(dp->aux); } @@ -566,7 +577,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); dp->ctrl = NULL; - goto error_ctrl; + goto error_link; } dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); @@ -574,13 +585,11 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) rc = PTR_ERR(dp->audio); pr_err("failed to initialize audio, rc = %d\n", rc); dp->audio = NULL; - goto error_ctrl; + goto error_link; } return rc; -error_ctrl: - msm_dp_panel_put(dp->panel); error_link: msm_dp_aux_put(dp->aux); error: @@ -744,8 +753,7 @@ int msm_dp_display_get_modes(struct msm_dp *dp) msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - return msm_dp_panel_get_modes(msm_dp_display->panel, - dp->connector); + return drm_edid_connector_add_modes(msm_dp_display->panel->connector); } bool msm_dp_display_check_video_test(struct msm_dp *dp) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 6bb021820d7c5..bde4a772d22c0 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -232,8 +232,8 @@ static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel, return min_supported_bpp; } -int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, + struct drm_connector *connector) { int rc, bw_code; int count; @@ -271,36 +271,9 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd, msm_dp_panel->downstream_ports); - if (rc) - return rc; - - drm_edid_free(msm_dp_panel->drm_edid); - - msm_dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc); - - drm_edid_connector_update(connector, msm_dp_panel->drm_edid); - - if (!msm_dp_panel->drm_edid) { - DRM_ERROR("panel edid read failed\n"); - /* check edid read fail is due to unplug */ - if (!msm_dp_aux_is_link_connected(panel->aux)) { - rc = -ETIMEDOUT; - goto end; - } - } - -end: return rc; } -void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) -{ - drm_edid_connector_update(connector, NULL); - drm_edid_free(msm_dp_panel->drm_edid); - msm_dp_panel->drm_edid = NULL; -} - u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_edid_bpp, u32 mode_pclk_khz) { @@ -324,20 +297,6 @@ u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, return bpp; } -int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) -{ - if (!msm_dp_panel) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - if (msm_dp_panel->drm_edid) - return drm_edid_connector_add_modes(connector); - - return 0; -} - static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) { edid += edid->extensions; @@ -345,7 +304,8 @@ static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) return edid->checksum; } -void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) +void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, + const struct drm_edid *drm_edid) { struct msm_dp_panel_private *panel; @@ -358,7 +318,7 @@ void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { /* FIXME: get rid of drm_edid_raw() */ - const struct edid *edid = drm_edid_raw(msm_dp_panel->drm_edid); + const struct edid *edid = drm_edid_raw(drm_edid); u8 checksum; if (edid) @@ -755,10 +715,3 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux return msm_dp_panel; } -void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel) -{ - if (!msm_dp_panel) - return; - - drm_edid_free(msm_dp_panel->drm_edid); -} diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 9173e90a50530..53b7b4463551f 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -33,7 +33,6 @@ struct msm_dp_panel { u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct msm_dp_link_info link_info; - const struct drm_edid *drm_edid; struct drm_connector *connector; struct msm_dp_display_mode msm_dp_mode; struct msm_dp_panel_psr psr_cap; @@ -47,15 +46,12 @@ struct msm_dp_panel { int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); -int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); -void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, + struct drm_connector *connector); u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, u32 mode_pclk_khz); -int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); -void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel); +void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, + const struct drm_edid *drm_edid); void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); @@ -94,5 +90,4 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux struct msm_dp_link *link, void __iomem *link_base, void __iomem *p0_base); -void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); #endif /* _DP_PANEL_H_ */ From d3a8dc478112f0a3070e84600627f61183973295 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:24 +0800 Subject: [PATCH 0727/1058] FROMLIST: drm/msm/dp: drop deprecated .mode_set() and use .atomic_enable The bridge .mode_set() callback is deprecated. Remove it and move all mode setup logic to .atomic_enable(), where the adjusted_mode is available from the atomic CRTC state. Drop msm_dp_mode from msm_dp_display_private and store the mode directly in the panel, as it was only used as a temporary cache. Both changes are limited to msm_dp_display_set_mode and are kept in a single patch. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-2-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 81 +++++++++++------------------ drivers/gpu/drm/msm/dp/dp_drm.c | 2 - drivers/gpu/drm/msm/dp/dp_drm.h | 3 -- 3 files changed, 31 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bce165bac106b..57eafd4724627 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -63,7 +63,6 @@ struct msm_dp_display_private { struct msm_dp_panel *panel; struct msm_dp_ctrl *ctrl; - struct msm_dp_display_mode msm_dp_mode; struct msm_dp msm_dp_display; /* wait for audio signaling */ @@ -597,16 +596,33 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) } static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, - struct msm_dp_display_mode *mode) + const struct drm_display_mode *adjusted_mode, + struct msm_dp_panel *msm_dp_panel) { struct msm_dp_display_private *dp; + u32 bpp; dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - drm_mode_copy(&dp->panel->msm_dp_mode.drm_mode, &mode->drm_mode); - dp->panel->msm_dp_mode.bpp = mode->bpp; - dp->panel->msm_dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420; - msm_dp_panel_init_panel_info(dp->panel); + drm_mode_copy(&msm_dp_panel->msm_dp_mode.drm_mode, adjusted_mode); + if (msm_dp_display_check_video_test(msm_dp_display)) + bpp = msm_dp_display_get_test_bpp(msm_dp_display); + else + bpp = msm_dp_panel->connector->display_info.bpc * 3; + + msm_dp_panel->msm_dp_mode.bpp = bpp ? bpp : 24; /* Default bpp */ + msm_dp_panel->msm_dp_mode.v_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC); + msm_dp_panel->msm_dp_mode.h_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); + msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = + drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && + msm_dp_panel->vsc_sdp_supported; + msm_dp_panel_init_panel_info(msm_dp_panel); + + /* populate wide_bus_support to different layers */ + dp->ctrl->wide_bus_en = + msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 ? false : dp->wide_bus_supported; return 0; } @@ -1309,7 +1325,7 @@ bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - if (dp->msm_dp_mode.out_fmt_is_yuv_420) + if (dp->panel->msm_dp_mode.out_fmt_is_yuv_420) return false; return dp->wide_bus_supported; @@ -1365,15 +1381,19 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; int rc = 0; struct msm_dp_display_private *msm_dp_display; bool force_link_train = false; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - if (!msm_dp_display->msm_dp_mode.drm_mode.clock) { - DRM_ERROR("invalid params\n"); + + crtc = drm_atomic_get_new_crtc_for_encoder(state, + drm_bridge->encoder); + if (!crtc) return; - } + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); if (dp->is_edp) msm_dp_hpd_plug_handle(msm_dp_display); @@ -1386,7 +1406,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, if (msm_dp_display->link->sink_count == 0) return; - rc = msm_dp_display_set_mode(dp, &msm_dp_display->msm_dp_mode); + rc = msm_dp_display_set_mode(dp, &crtc_state->adjusted_mode, msm_dp_display->panel); if (rc) { DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); return; @@ -1446,45 +1466,6 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, pm_runtime_put_sync(&dp->pdev->dev); } -void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) -{ - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; - struct msm_dp_display_private *msm_dp_display; - struct msm_dp_panel *msm_dp_panel; - - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - msm_dp_panel = msm_dp_display->panel; - - memset(&msm_dp_display->msm_dp_mode, 0x0, sizeof(struct msm_dp_display_mode)); - - if (msm_dp_display_check_video_test(dp)) - msm_dp_display->msm_dp_mode.bpp = msm_dp_display_get_test_bpp(dp); - else /* Default num_components per pixel = 3 */ - msm_dp_display->msm_dp_mode.bpp = dp->connector->display_info.bpc * 3; - - if (!msm_dp_display->msm_dp_mode.bpp) - msm_dp_display->msm_dp_mode.bpp = 24; /* Default bpp */ - - drm_mode_copy(&msm_dp_display->msm_dp_mode.drm_mode, adjusted_mode); - - msm_dp_display->msm_dp_mode.v_active_low = - !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC); - - msm_dp_display->msm_dp_mode.h_active_low = - !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); - - msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 = - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) && - msm_dp_panel->vsc_sdp_supported; - - /* populate wide_bus_support to different layers */ - msm_dp_display->ctrl->wide_bus_en = - msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported; -} - void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index b659d22f5f284..6ac5bac903d98 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -56,7 +56,6 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = { .atomic_enable = msm_dp_bridge_atomic_enable, .atomic_disable = msm_dp_bridge_atomic_disable, .atomic_post_disable = msm_dp_bridge_atomic_post_disable, - .mode_set = msm_dp_bridge_mode_set, .mode_valid = msm_dp_bridge_mode_valid, .get_modes = msm_dp_bridge_get_modes, .detect = msm_dp_bridge_detect, @@ -233,7 +232,6 @@ static const struct drm_bridge_funcs msm_edp_bridge_ops = { .atomic_enable = msm_edp_bridge_atomic_enable, .atomic_disable = msm_edp_bridge_atomic_disable, .atomic_post_disable = msm_edp_bridge_atomic_post_disable, - .mode_set = msm_dp_bridge_mode_set, .mode_valid = msm_edp_bridge_mode_valid, .atomic_reset = drm_atomic_helper_bridge_reset, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 041aa026ae2ee..4bd788ea05d5b 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -36,9 +36,6 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode); -void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode); void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, From b17d6bd650f892a96fa6fc0e9b9db4c0c4960bbe Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:25 +0800 Subject: [PATCH 0728/1058] FROMLIST: drm/msm/dp: move mode setup into msm_dp_panel_init_panel_info() The display layer directly assigns msm_dp_panel mode fields (bpp, sync polarity, yuv420 flag) instead of letting the panel manage its own state. Pass adjusted_mode and bpp as parameters to msm_dp_panel_init_panel_info() and move the assignments inside it. Suggested-by: Dmitry Baryshkov Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-3-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 11 +---------- drivers/gpu/drm/msm/dp/dp_panel.c | 18 +++++++++++++++--- drivers/gpu/drm/msm/dp/dp_panel.h | 4 +++- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 57eafd4724627..155beefdfdef2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -604,21 +604,12 @@ static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - drm_mode_copy(&msm_dp_panel->msm_dp_mode.drm_mode, adjusted_mode); if (msm_dp_display_check_video_test(msm_dp_display)) bpp = msm_dp_display_get_test_bpp(msm_dp_display); else bpp = msm_dp_panel->connector->display_info.bpc * 3; - msm_dp_panel->msm_dp_mode.bpp = bpp ? bpp : 24; /* Default bpp */ - msm_dp_panel->msm_dp_mode.v_active_low = - !!(adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC); - msm_dp_panel->msm_dp_mode.h_active_low = - !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); - msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = - drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && - msm_dp_panel->vsc_sdp_supported; - msm_dp_panel_init_panel_info(msm_dp_panel); + msm_dp_panel_init_panel_info(msm_dp_panel, adjusted_mode, bpp ? bpp : 24); /* populate wide_bus_support to different layers */ dp->ctrl->wide_bus_en = diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index bde4a772d22c0..e76dad0f66637 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -647,15 +647,27 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) return 0; } -int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel) +int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, + const struct drm_display_mode *adjusted_mode, + u32 bpp) { struct drm_display_mode *drm_mode; struct msm_dp_panel_private *panel; - drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; - panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + drm_mode_copy(&msm_dp_panel->msm_dp_mode.drm_mode, adjusted_mode); + msm_dp_panel->msm_dp_mode.bpp = bpp; + msm_dp_panel->msm_dp_mode.v_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC); + msm_dp_panel->msm_dp_mode.h_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); + msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = + drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && + msm_dp_panel->vsc_sdp_supported; + + drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; + /* * print resolution info as this is a result * of user initiated action of cable connection diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 53b7b4463551f..4519ac3742206 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -43,7 +43,9 @@ struct msm_dp_panel { u32 max_bw_code; }; -int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); +int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, + const struct drm_display_mode *adjusted_mode, + u32 bpp); int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, From 47a8b597f935c92af0a1181d3482a3036c5cb828 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:26 +0800 Subject: [PATCH 0729/1058] FROMLIST: drm/msm/dp: split msm_dp_ctrl_config_ctrl() into link parts and stream parts The DP_CONFIGURATION_CTRL register contains both link-level and stream-specific fields. Currently, msm_dp_ctrl_config_ctrl() configures all of them together. Separate the configuration into link parts and stream parts to support MST. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-4-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 46 +++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 86ef8c89ad443..ed2ba47881fd0 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -388,26 +388,44 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); } -static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *msm_dp_panel) { u32 config = 0, tbd; + + /* + * RMW: Called from atomic_enable(). Serialized by the DRM atomic framework. + */ + config = msm_dp_read_link(ctrl, REG_DP_CONFIGURATION_CTRL); + + if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) + config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ + + tbd = msm_dp_link_get_test_bits_depth(ctrl->link, + msm_dp_panel->msm_dp_mode.bpp); + + config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; + + if (msm_dp_panel->psr_cap.version) + config |= DP_CONFIGURATION_CTRL_SEND_VSC; + + drm_dbg_dp(ctrl->drm_dev, "stream DP_CONFIGURATION_CTRL=0x%x\n", config); + + msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); +} + +static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl) +{ + u32 config = 0; const u8 *dpcd = ctrl->panel->dpcd; /* Default-> LSCLK DIV: 1/4 LCLK */ config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); - if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) - config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ - /* Scrambler reset enable */ if (drm_dp_alternate_scrambler_reset_cap(dpcd)) config |= DP_CONFIGURATION_CTRL_ASSR; - tbd = msm_dp_link_get_test_bits_depth(ctrl->link, - ctrl->panel->msm_dp_mode.bpp); - - config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; - /* Num of Lanes */ config |= ((ctrl->link->link_params.num_lanes - 1) << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT); @@ -421,10 +439,7 @@ static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; - if (ctrl->panel->psr_cap.version) - config |= DP_CONFIGURATION_CTRL_SEND_VSC; - - drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config); + drm_dbg_dp(ctrl->drm_dev, "link DP_CONFIGURATION_CTRL=0x%x\n", config); msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); } @@ -450,7 +465,8 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl msm_dp_ctrl_lane_mapping(ctrl); msm_dp_setup_peripheral_flush(ctrl); - msm_dp_ctrl_config_ctrl(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl); + msm_dp_ctrl_config_ctrl_streams(ctrl, ctrl->panel); test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp); colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); @@ -1628,7 +1644,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, u8 assr; struct msm_dp_link_info link_info = {0}; - msm_dp_ctrl_config_ctrl(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl); link_info.num_lanes = ctrl->link->link_params.num_lanes; link_info.rate = ctrl->link->link_params.rate; From 5db493928ba56572c0fdd270362160365ea205f0 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:27 +0800 Subject: [PATCH 0730/1058] FROMLIST: drm/msm/dp: extract MISC1_MISC0 configuration into a separate function Refactor the MISC1_MISC0 register configuration into a standalone helper function to support MST. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-5-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index ed2ba47881fd0..71d45b2c4daf8 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -458,17 +458,13 @@ static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl) ln_mapping); } -static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *msm_dp_panel) { u32 colorimetry_cfg, test_bits_depth, misc_val; - msm_dp_ctrl_lane_mapping(ctrl); - msm_dp_setup_peripheral_flush(ctrl); - - msm_dp_ctrl_config_ctrl_link(ctrl); - msm_dp_ctrl_config_ctrl_streams(ctrl, ctrl->panel); - - test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp); + test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, + msm_dp_panel->msm_dp_mode.bpp); colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); @@ -482,6 +478,17 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); +} + +static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) +{ + msm_dp_ctrl_lane_mapping(ctrl); + msm_dp_setup_peripheral_flush(ctrl); + + msm_dp_ctrl_config_ctrl_link(ctrl); + msm_dp_ctrl_config_ctrl_streams(ctrl, ctrl->panel); + + msm_dp_ctrl_config_misc1_misc0(ctrl, ctrl->panel); msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en); } From 573a1aa88d4a3eaf5774a4fbea7ecd5f5e4db31f Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:28 +0800 Subject: [PATCH 0731/1058] FROMLIST: drm/msm/dp: split link setup from source params msm_dp_ctrl_configure_source_params() should only handle stream-related configuration. Move the link setup out of it so MST can program link and stream settings separately. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-6-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 71d45b2c4daf8..1c2eccec6ec6d 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -482,10 +482,6 @@ static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) { - msm_dp_ctrl_lane_mapping(ctrl); - msm_dp_setup_peripheral_flush(ctrl); - - msm_dp_ctrl_config_ctrl_link(ctrl); msm_dp_ctrl_config_ctrl_streams(ctrl, ctrl->panel); msm_dp_ctrl_config_misc1_misc0(ctrl, ctrl->panel); @@ -2551,6 +2547,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train */ reinit_completion(&ctrl->video_comp); + msm_dp_ctrl_lane_mapping(ctrl); + msm_dp_setup_peripheral_flush(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl); + msm_dp_ctrl_configure_source_params(ctrl); msm_dp_ctrl_config_msa(ctrl, From 162c0a62eaf1bf6259e0cf386b58aa08003b2991 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:29 +0800 Subject: [PATCH 0732/1058] FROMLIST: drm/msm/dp: move the pixel clock control to its own API Enable/Disable of DP pixel clock happens in multiple code paths leading to code duplication. Move it into individual helpers so that the helpers can be called wherever necessary. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-7-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 80 ++++++++++++++++---------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 1c2eccec6ec6d..a2c44088e6a68 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2171,6 +2171,41 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return success; } +static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate) +{ + int ret; + + ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); + if (ret) { + DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); + return ret; + } + + if (WARN_ON_ONCE(ctrl->stream_clks_on)) + return 0; + + ret = clk_prepare_enable(ctrl->pixel_clk); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + return ret; + } + ctrl->stream_clks_on = true; + + return ret; +} + +static void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (ctrl->stream_clks_on) { + clk_disable_unprepare(ctrl->pixel_clk); + ctrl->stream_clks_on = false; + } +} + static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl) { int ret; @@ -2196,22 +2231,7 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl } pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); - if (ret) { - DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); - return ret; - } - - if (ctrl->stream_clks_on) { - drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); - } else { - ret = clk_prepare_enable(ctrl->pixel_clk); - if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); - return ret; - } - ctrl->stream_clks_on = true; - } + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); msm_dp_ctrl_send_phy_test_pattern(ctrl); @@ -2514,26 +2534,13 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); if (ret) { DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); - goto end; + return ret; } } - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); - if (ret) { - DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); - goto end; - } - - if (ctrl->stream_clks_on) { - drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); - } else { - ret = clk_prepare_enable(ctrl->pixel_clk); - if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); - goto end; - } - ctrl->stream_clks_on = true; - } + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); + if (ret) + return ret; if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) msm_dp_ctrl_link_retrain(ctrl); @@ -2572,7 +2579,6 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train drm_dbg_dp(ctrl->drm_dev, "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); -end: return ret; } @@ -2620,11 +2626,7 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); - if (ctrl->stream_clks_on) { - clk_disable_unprepare(ctrl->pixel_clk); - ctrl->stream_clks_on = false; - } - + msm_dp_ctrl_off_pixel_clk(msm_dp_ctrl); dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); From bacf81c9a76832ec3137412b7b803f172c264e63 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:30 +0800 Subject: [PATCH 0733/1058] FROMLIST: drm/msm/dp: break up dp_display_enable into two parts dp_display_enable() currently re-trains the link if needed and then enables the pixel clock, programs the controller to start sending the pixel stream. Split these two parts into prepare/enable APIs, to support MST bridges_enable insert the MST payloads funcs between enable stream_clks and program register. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-8-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 48 ++++++++----- drivers/gpu/drm/msm/dp/dp_ctrl.h | 3 +- drivers/gpu/drm/msm/dp/dp_display.c | 105 ++++++++++++++++++---------- 3 files changed, 102 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index a2c44088e6a68..546d899dde237 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2504,27 +2504,19 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); } -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) { int ret = 0; - bool mainlink_ready = false; struct msm_dp_ctrl_private *ctrl; - unsigned long pixel_rate; - unsigned long pixel_rate_orig; if (!msm_dp_ctrl) return -EINVAL; ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - pixel_rate = pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock; - - if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) - pixel_rate >>= 1; - - drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n", - ctrl->link->link_params.rate, - ctrl->link->link_params.num_lanes, pixel_rate); + drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d\n", + ctrl->link->link_params.rate, + ctrl->link->link_params.num_lanes); drm_dbg_dp(ctrl->drm_dev, "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", @@ -2538,16 +2530,40 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train } } - ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); - if (ret) - return ret; - if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) msm_dp_ctrl_link_retrain(ctrl); /* stop txing train pattern to end link training */ msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + return ret; +} + +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl) +{ + int ret = 0; + bool mainlink_ready = false; + struct msm_dp_ctrl_private *ctrl; + unsigned long pixel_rate; + unsigned long pixel_rate_orig; + + if (!msm_dp_ctrl) + return -EINVAL; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock; + pixel_rate = pixel_rate_orig; + + if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) + pixel_rate >>= 1; + + drm_dbg_dp(ctrl->drm_dev, "pixel_rate=%lu\n", pixel_rate); + + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); + if (ret) + return ret; + /* * Set up transfer unit values and set controller state to send * video. diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index f68bee62713f1..1497f1a8fc2f0 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -17,7 +17,8 @@ struct msm_dp_ctrl { struct phy; int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl); -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl); +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 155beefdfdef2..2cf4c984c7ca7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -617,7 +617,40 @@ static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, return 0; } -static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_link_train) +static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) +{ + struct msm_dp *msm_dp_display = &dp->msm_dp_display; + int rc = 0; + bool force_link_train = false; + + drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); + + if (msm_dp_display->is_edp) + msm_dp_hpd_plug_handle(dp); + + rc = pm_runtime_resume_and_get(&msm_dp_display->pdev->dev); + if (rc) { + DRM_ERROR("failed to pm_runtime_resume\n"); + return rc; + } + + if (dp->link->sink_count == 0) + return rc; + + if (!msm_dp_display->power_on) { + msm_dp_display_host_phy_init(dp); + force_link_train = true; + } + + rc = msm_dp_ctrl_on_link(dp->ctrl); + if (rc) + DRM_ERROR("Failed link training (rc=%d)\n", rc); + // TODO: schedule drm_connector_set_link_status_property() + + return msm_dp_ctrl_prepare_stream_on(dp->ctrl, force_link_train); +} + +static int msm_dp_display_enable(struct msm_dp_display_private *dp) { int rc = 0; struct msm_dp *msm_dp_display = &dp->msm_dp_display; @@ -628,7 +661,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_l return 0; } - rc = msm_dp_ctrl_on_stream(dp->ctrl, force_link_train); + rc = msm_dp_ctrl_on_stream(dp->ctrl); if (!rc) msm_dp_display->power_on = true; @@ -658,13 +691,10 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display) return 0; } -static int msm_dp_display_disable(struct msm_dp_display_private *dp) +static void msm_dp_display_audio_notify_disable(struct msm_dp_display_private *dp) { struct msm_dp *msm_dp_display = &dp->msm_dp_display; - if (!msm_dp_display->power_on) - return 0; - /* wait only if audio was enabled */ if (msm_dp_display->audio_enabled) { /* signal the disconnect event */ @@ -675,6 +705,14 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) } msm_dp_display->audio_enabled = false; +} + +static int msm_dp_display_disable(struct msm_dp_display_private *dp) +{ + struct msm_dp *msm_dp_display = &dp->msm_dp_display; + + if (!msm_dp_display->power_on) + return 0; if (dp->link->sink_count == 0) { /* @@ -1371,14 +1409,13 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, struct drm_atomic_commit *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; + struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; int rc = 0; - struct msm_dp_display_private *msm_dp_display; - bool force_link_train = false; + struct msm_dp_display_private *dp; - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_bridge->encoder); @@ -1386,44 +1423,29 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - if (dp->is_edp) - msm_dp_hpd_plug_handle(msm_dp_display); - - if (pm_runtime_resume_and_get(&dp->pdev->dev)) { - DRM_ERROR("failed to pm_runtime_resume\n"); - return; - } - - if (msm_dp_display->link->sink_count == 0) - return; - - rc = msm_dp_display_set_mode(dp, &crtc_state->adjusted_mode, msm_dp_display->panel); + rc = msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, dp->panel); if (rc) { DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); return; } - if (!dp->power_on) { - msm_dp_display_host_phy_init(msm_dp_display); - force_link_train = true; - } - - rc = msm_dp_ctrl_on_link(msm_dp_display->ctrl); + rc = msm_dp_display_prepare_link(dp); if (rc) { - DRM_ERROR("Failed link training (rc=%d)\n", rc); - // TODO: schedule drm_connector_set_link_status_property() + DRM_ERROR("DP display prepare failed, rc=%d\n", rc); return; } - msm_dp_display_enable(msm_dp_display, force_link_train); + rc = msm_dp_display_enable(dp); + if (rc) + DRM_ERROR("DP display enable failed, rc=%d\n", rc); - rc = msm_dp_display_post_enable(dp); + rc = msm_dp_display_post_enable(msm_dp_display); if (rc) { DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(msm_dp_display); + msm_dp_display_disable(dp); } - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); + drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, @@ -1438,6 +1460,15 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, msm_dp_ctrl_push_idle(msm_dp_display->ctrl); } +static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) +{ + struct msm_dp *msm_dp_display = &dp->msm_dp_display; + + pm_runtime_put_sync(&msm_dp_display->pdev->dev); + + drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); +} + void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, struct drm_atomic_commit *state) { @@ -1450,11 +1481,11 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, if (dp->is_edp) msm_dp_hpd_unplug_handle(msm_dp_display); - msm_dp_display_disable(msm_dp_display); + msm_dp_display_audio_notify_disable(msm_dp_display); - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); + msm_dp_display_disable(msm_dp_display); - pm_runtime_put_sync(&dp->pdev->dev); + msm_dp_display_unprepare(msm_dp_display); } void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) From 26eca453a444e0458b5d6a9466b63b3bfcfe15cf Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:31 +0800 Subject: [PATCH 0734/1058] FROMLIST: drm/msm/dp: re-arrange dp_display_disable() into functional parts dp_display_disable() handles special case of when monitor is disconnected from the dongle while the dongle stays connected thereby needing a separate function dp_ctrl_off_link_stream() for this. However with a slight rework this can still be handled by keeping common paths same for regular and special case. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-9-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 19 +------------------ drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 10 +++++++++- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 546d899dde237..626b95d4d0159 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2598,7 +2598,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl) return ret; } -void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; struct phy *phy; @@ -2606,23 +2606,6 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_panel_disable_vsc_sdp(ctrl->panel); - - /* set dongle to D3 (power off) mode */ - msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); - - msm_dp_ctrl_mainlink_disable(ctrl); - - if (ctrl->stream_clks_on) { - clk_disable_unprepare(ctrl->pixel_clk); - ctrl->stream_clks_on = false; - } - - dev_pm_opp_set_rate(ctrl->dev, 0); - msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); - - phy_power_off(phy); - /* aux channel down, reinit phy */ phy_exit(phy); phy_init(phy); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 1497f1a8fc2f0..5d615f50d13bf 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -19,7 +19,6 @@ struct phy; int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl); int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl); int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); -void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); @@ -46,4 +45,5 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2cf4c984c7ca7..e1d90b8539c27 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -714,12 +714,20 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) if (!msm_dp_display->power_on) return 0; + msm_dp_panel_disable_vsc_sdp(dp->panel); + + /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) { /* * irq_hpd with sink_count = 0 * hdmi unplugged out of dongle */ - msm_dp_ctrl_off_link_stream(dp->ctrl); + + /* set dongle to D3 (power off) mode */ + msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); + msm_dp_ctrl_off(dp->ctrl); + /* re-init the PHY so that we can listen to Dongle disconnect */ + msm_dp_ctrl_reinit_phy(dp->ctrl); } else { /* * unplugged interrupt From 57a5c455b4eb1d853f59915944cfccf9c50e22b5 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:32 +0800 Subject: [PATCH 0735/1058] FROMLIST: drm/msm/dp: allow dp_ctrl stream APIs to use any panel passed to it With MST, multiple sinks share a single DP controller, so a cached panel in msm_dp_ctrl_private can no longer represent the per-stream sink. Drop the cache and pass panel explicitly to all stream-related dp_ctrl APIs. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-10-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 196 ++++++++++++++++------------ drivers/gpu/drm/msm/dp/dp_ctrl.h | 28 ++-- drivers/gpu/drm/msm/dp/dp_display.c | 24 ++-- 3 files changed, 140 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 626b95d4d0159..87c3a5517911f 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -114,7 +114,6 @@ struct msm_dp_ctrl_private { struct drm_device *drm_dev; struct device *dev; struct drm_dp_aux *aux; - struct msm_dp_panel *panel; struct msm_dp_link *link; void __iomem *ahb_base; void __iomem *link_base; @@ -202,7 +201,8 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ -void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); @@ -219,7 +219,7 @@ void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) if (!ctrl->hw_revision) { ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); - ctrl->panel->hw_revision = ctrl->hw_revision; + panel->hw_revision = ctrl->hw_revision; } } @@ -414,10 +414,11 @@ static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); } -static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { u32 config = 0; - const u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = panel->dpcd; /* Default-> LSCLK DIV: 1/4 LCLK */ config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); @@ -480,13 +481,14 @@ static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); } -static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { - msm_dp_ctrl_config_ctrl_streams(ctrl, ctrl->panel); + msm_dp_ctrl_config_ctrl_streams(ctrl, panel); - msm_dp_ctrl_config_misc1_misc0(ctrl, ctrl->panel); + msm_dp_ctrl_config_misc1_misc0(ctrl, panel); - msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en); + msm_dp_panel_timing_cfg(panel, ctrl->msm_dp_ctrl.wide_bus_en); } /* @@ -1256,20 +1258,21 @@ static void _dp_ctrl_calc_tu(struct msm_dp_ctrl_private *ctrl, } static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, struct msm_dp_vc_tu_mapping_table *tu_table) { struct msm_dp_tu_calc_input in; - struct drm_display_mode *drm_mode; + const struct drm_display_mode *drm_mode; - drm_mode = &ctrl->panel->msm_dp_mode.drm_mode; + drm_mode = &panel->msm_dp_mode.drm_mode; in.lclk = ctrl->link->link_params.rate / 1000; in.pclk_khz = drm_mode->clock; in.hactive = drm_mode->hdisplay; in.hporch = drm_mode->htotal - drm_mode->hdisplay; in.nlanes = ctrl->link->link_params.num_lanes; - in.bpp = ctrl->panel->msm_dp_mode.bpp; - in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; + in.bpp = panel->msm_dp_mode.bpp; + in.pixel_enc = panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; in.dsc_en = 0; in.async_en = 0; in.fec_en = 0; @@ -1279,14 +1282,15 @@ static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, _dp_ctrl_calc_tu(ctrl, &in, tu_table); } -static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { u32 msm_dp_tu = 0x0; u32 valid_boundary = 0x0; u32 valid_boundary2 = 0x0; struct msm_dp_vc_tu_mapping_table tu_calc_table; - msm_dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table); + msm_dp_ctrl_calc_tu_parameters(ctrl, panel, &tu_calc_table); msm_dp_tu |= tu_calc_table.tu_size_minus1; valid_boundary |= tu_calc_table.valid_boundary_link; @@ -1438,6 +1442,7 @@ static int msm_dp_ctrl_set_pattern_state_bit(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int delay_us; @@ -1446,7 +1451,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, int const maximum_retries = 4; delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); @@ -1532,14 +1537,15 @@ static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ctrl) return ret; } -static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { if (ctrl->link->link_params.num_lanes == 1) return -1; ctrl->link->link_params.num_lanes /= 2; - ctrl->link->link_params.rate = ctrl->panel->link_info.rate; + ctrl->link->link_params.rate = panel->link_info.rate; ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; @@ -1548,6 +1554,7 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) } static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, enum drm_dp_phy dp_phy) { int delay_us; @@ -1555,11 +1562,12 @@ static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int delay_us; @@ -1570,16 +1578,16 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, u8 link_status[DP_LINK_STATUS_SIZE]; delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); *training_step = DP_TRAINING_2; - if (drm_dp_tps4_supported(ctrl->panel->dpcd)) { + if (drm_dp_tps4_supported(panel->dpcd)) { pattern = DP_TRAINING_PATTERN_4; state_ctrl_bit = 4; - } else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) { + } else if (drm_dp_tps3_supported(panel->dpcd)) { pattern = DP_TRAINING_PATTERN_3; state_ctrl_bit = 3; } else { @@ -1616,18 +1624,19 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int ret; - ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + ret = msm_dp_ctrl_link_train_1(ctrl, panel, training_step, dp_phy); if (ret) { DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); return ret; } drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); - ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + ret = msm_dp_ctrl_link_train_2(ctrl, panel, training_step, dp_phy); if (ret) { DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); return ret; @@ -1638,16 +1647,17 @@ static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step) { int i; int ret = 0; - const u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; u8 assr; struct msm_dp_link_info link_info = {0}; - msm_dp_ctrl_config_ctrl_link(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl, panel); link_info.num_lanes = ctrl->link->link_params.num_lanes; link_info.rate = ctrl->link->link_params.rate; @@ -1670,8 +1680,8 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); - ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); - msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, dp_phy); if (ret) break; @@ -1682,7 +1692,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, goto end; } - ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); + ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, DP_PHY_DPRX); if (ret) { DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; @@ -1695,6 +1705,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step) { int ret = 0; @@ -1710,7 +1721,7 @@ static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, * a link training pattern, we have to first do soft reset. */ - ret = msm_dp_ctrl_link_train(ctrl, training_step); + ret = msm_dp_ctrl_link_train(ctrl, panel, training_step); return ret; } @@ -1809,11 +1820,12 @@ static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) str_on_off(ctrl->core_clks_on)); } -static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret = 0; struct phy *phy = ctrl->phy; - const u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = panel->dpcd; ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100; @@ -1865,13 +1877,14 @@ static void msm_dp_ctrl_psr_exit(struct msm_dp_ctrl_private *ctrl) msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); } -void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); u32 cfg; - if (!ctrl->panel->psr_cap.version) + if (!panel->psr_cap.version) return; /* enable PSR1 function */ @@ -1886,12 +1899,13 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1); } -void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter) +void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, bool enter) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - if (!ctrl->panel->psr_cap.version) + if (!panel->psr_cap.version) return; /* @@ -1961,7 +1975,8 @@ void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl) phy_exit(phy); } -static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { struct phy *phy = ctrl->phy; int ret = 0; @@ -1982,7 +1997,7 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) /* hw recommended delay before re-enabling clocks */ msleep(20); - ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (ret) { DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); return ret; @@ -1991,7 +2006,8 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) return ret; } -static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { struct phy *phy; @@ -1999,7 +2015,7 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) msm_dp_ctrl_mainlink_disable(ctrl); - msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); @@ -2013,7 +2029,8 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) return 0; } -static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret = 0; int training_step = DP_TRAINING_NONE; @@ -2023,11 +2040,11 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; - ret = msm_dp_ctrl_setup_main_link(ctrl, &training_step); + ret = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); @@ -2206,7 +2223,8 @@ static void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) } } -static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret; unsigned long pixel_rate; @@ -2222,15 +2240,15 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl * running. Add the global reset just before disabling the * link clocks and core clocks. */ - msm_dp_ctrl_off(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_off(&ctrl->msm_dp_ctrl, panel); - ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl); + ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl, panel); if (ret) { DRM_ERROR("failed to enable DP link controller\n"); return ret; } - pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; + pixel_rate = panel->msm_dp_mode.drm_mode.clock; ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); msm_dp_ctrl_send_phy_test_pattern(ctrl); @@ -2238,7 +2256,8 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl return 0; } -void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; u32 sink_request = 0x0; @@ -2253,14 +2272,14 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n"); - if (msm_dp_ctrl_process_phy_test_request(ctrl)) { + if (msm_dp_ctrl_process_phy_test_request(ctrl, panel)) { DRM_ERROR("process phy_test_req failed\n"); return; } } if (sink_request & DP_LINK_STATUS_UPDATED) { - if (msm_dp_ctrl_link_maintenance(ctrl)) { + if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); return; } @@ -2268,7 +2287,7 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) if (sink_request & DP_TEST_LINK_TRAINING) { msm_dp_link_send_test_response(ctrl->link); - if (msm_dp_ctrl_link_maintenance(ctrl)) { + if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); return; } @@ -2304,7 +2323,8 @@ static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl) return drm_dp_channel_eq_ok(link_status, num_lanes); } -int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) +int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { int rc = 0; struct msm_dp_ctrl_private *ctrl; @@ -2320,8 +2340,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - rate = ctrl->panel->link_info.rate; - pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; + rate = panel->link_info.rate; + pixel_rate = panel->msm_dp_mode.drm_mode.clock; msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl); @@ -2333,8 +2353,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } else { ctrl->link->link_params.rate = rate; ctrl->link->link_params.num_lanes = - ctrl->panel->link_info.num_lanes; - if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) + panel->link_info.num_lanes; + if (panel->msm_dp_mode.out_fmt_is_yuv_420) pixel_rate >>= 1; } @@ -2342,13 +2362,13 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, pixel_rate); - rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (rc) return rc; while (--link_train_max_retries) { training_step = DP_TRAINING_NONE; - rc = msm_dp_ctrl_setup_main_link(ctrl, &training_step); + rc = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); if (rc == 0) { /* training completed successfully */ break; @@ -2367,7 +2387,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * some lanes are ready, * reduce lane number */ - rc = msm_dp_ctrl_link_lane_down_shift(ctrl); + rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); if (rc < 0) { /* lane == 1 already */ /* end with failure */ break; @@ -2388,7 +2408,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl->link->link_params.num_lanes)) rc = msm_dp_ctrl_link_rate_down_shift(ctrl); else - rc = msm_dp_ctrl_link_lane_down_shift(ctrl); + rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); if (rc < 0) { /* end with failure */ @@ -2396,10 +2416,10 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); } - rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); + rc = msm_dp_ctrl_reinitialize_mainlink(ctrl, panel); if (rc) { DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); break; @@ -2420,20 +2440,21 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); - msm_dp_ctrl_deinitialize_mainlink(ctrl); + msm_dp_ctrl_deinitialize_mainlink(ctrl, panel); rc = -ECONNRESET; } return rc; } -static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int training_step = DP_TRAINING_NONE; - return msm_dp_ctrl_setup_main_link(ctrl, &training_step); + return msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); } static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, @@ -2504,7 +2525,9 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); } -int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, + bool force_link_train) { int ret = 0; struct msm_dp_ctrl_private *ctrl; @@ -2523,7 +2546,7 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_li ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); if (!ctrl->link_clks_on) { /* link clk is off */ - ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (ret) { DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); return ret; @@ -2531,15 +2554,15 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_li } if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) - msm_dp_ctrl_link_retrain(ctrl); + msm_dp_ctrl_link_retrain(ctrl, panel); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); return ret; } -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl) +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) { int ret = 0; bool mainlink_ready = false; @@ -2552,10 +2575,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock; + pixel_rate_orig = panel->msm_dp_mode.drm_mode.clock; pixel_rate = pixel_rate_orig; - if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) + if (msm_dp_ctrl->wide_bus_en || panel->msm_dp_mode.out_fmt_is_yuv_420) pixel_rate >>= 1; drm_dbg_dp(ctrl->drm_dev, "pixel_rate=%lu\n", pixel_rate); @@ -2572,18 +2595,18 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl) msm_dp_ctrl_lane_mapping(ctrl); msm_dp_setup_peripheral_flush(ctrl); - msm_dp_ctrl_config_ctrl_link(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl, panel); - msm_dp_ctrl_configure_source_params(ctrl); + msm_dp_ctrl_configure_source_params(ctrl, panel); msm_dp_ctrl_config_msa(ctrl, ctrl->link->link_params.rate, pixel_rate_orig, - ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420); + panel->msm_dp_mode.out_fmt_is_yuv_420); - msm_dp_panel_clear_dsc_dto(ctrl->panel); + msm_dp_panel_clear_dsc_dto(panel); - msm_dp_ctrl_setup_tr_unit(ctrl); + msm_dp_ctrl_setup_tr_unit(ctrl, panel); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); @@ -2611,7 +2634,8 @@ void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl) phy_init(phy); } -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; struct phy *phy; @@ -2619,11 +2643,11 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_panel_disable_vsc_sdp(ctrl->panel); + msm_dp_panel_disable_vsc_sdp(panel); msm_dp_ctrl_mainlink_disable(ctrl); - msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); msm_dp_ctrl_off_pixel_clk(msm_dp_ctrl); dev_pm_opp_set_rate(ctrl->dev, 0); @@ -2632,7 +2656,8 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) phy_power_off(phy); } -irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) +irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; u32 isr; @@ -2643,7 +2668,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - if (ctrl->panel->psr_cap.version) { + if (panel->psr_cap.version) { isr = msm_dp_ctrl_get_psr_interrupt(ctrl); if (isr) @@ -2732,7 +2757,7 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) } struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, - struct msm_dp_panel *panel, struct drm_dp_aux *aux, + struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, void __iomem *link_base) @@ -2740,7 +2765,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link struct msm_dp_ctrl_private *ctrl; int ret; - if (!dev || !panel || !aux || !link) { + if (!dev || !aux || !link) { DRM_ERROR("invalid input\n"); return ERR_PTR(-EINVAL); } @@ -2768,7 +2793,6 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link init_completion(&ctrl->video_comp); /* in parameters */ - ctrl->panel = panel; ctrl->aux = aux; ctrl->link = link; ctrl->dev = dev; diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 5d615f50d13bf..00b430392a52e 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -16,28 +16,36 @@ struct msm_dp_ctrl { struct phy; -int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl); -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl); -int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); +int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, + bool force_link_train); +void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); -irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); -void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); +irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, - struct msm_dp_panel *panel, struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, void __iomem *link_base); -void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); -void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enable); -void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, bool enable); +void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index e1d90b8539c27..367d1d10af471 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -359,7 +359,7 @@ static void msm_dp_display_host_init(struct msm_dp_display_private *dp) dp->phy_initialized); msm_dp_ctrl_core_clk_enable(dp->ctrl); - msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_reset(dp->ctrl, dp->panel); msm_dp_ctrl_enable_irq(dp->ctrl); msm_dp_aux_init(dp->aux); dp->core_initialized = true; @@ -371,7 +371,7 @@ static void msm_dp_display_host_deinit(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_reset(dp->ctrl, dp->panel); msm_dp_ctrl_disable_irq(dp->ctrl); msm_dp_aux_deinit(dp->aux); msm_dp_ctrl_core_clk_disable(dp->ctrl); @@ -392,7 +392,7 @@ static int msm_dp_display_handle_irq_hpd(struct msm_dp_display_private *dp) drm_dbg_dp(dp->drm_dev, "%d\n", sink_request); - msm_dp_ctrl_handle_sink_request(dp->ctrl); + msm_dp_ctrl_handle_sink_request(dp->ctrl, dp->panel); if (sink_request & DP_TEST_LINK_VIDEO_PATTERN) msm_dp_display_handle_video_request(dp); @@ -570,7 +570,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, + dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->aux, phy, dp->ahb_base, dp->link_base); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); @@ -642,12 +642,12 @@ static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) force_link_train = true; } - rc = msm_dp_ctrl_on_link(dp->ctrl); + rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); if (rc) DRM_ERROR("Failed link training (rc=%d)\n", rc); // TODO: schedule drm_connector_set_link_status_property() - return msm_dp_ctrl_prepare_stream_on(dp->ctrl, force_link_train); + return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); } static int msm_dp_display_enable(struct msm_dp_display_private *dp) @@ -661,7 +661,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp) return 0; } - rc = msm_dp_ctrl_on_stream(dp->ctrl); + rc = msm_dp_ctrl_on_stream(dp->ctrl, dp->panel); if (!rc) msm_dp_display->power_on = true; @@ -686,7 +686,7 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display) msm_dp_display_handle_plugged_change(msm_dp_display, true); if (msm_dp_display->psr_supported) - msm_dp_ctrl_config_psr(dp->ctrl); + msm_dp_ctrl_config_psr(dp->ctrl, dp->panel); return 0; } @@ -725,7 +725,7 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) /* set dongle to D3 (power off) mode */ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); - msm_dp_ctrl_off(dp->ctrl); + msm_dp_ctrl_off(dp->ctrl, dp->panel); /* re-init the PHY so that we can listen to Dongle disconnect */ msm_dp_ctrl_reinit_phy(dp->ctrl); } else { @@ -733,7 +733,7 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) * unplugged interrupt * dongle unplugged out of DUT */ - msm_dp_ctrl_off(dp->ctrl); + msm_dp_ctrl_off(dp->ctrl, dp->panel); msm_dp_display_host_phy_exit(dp); } @@ -869,7 +869,7 @@ void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter) } dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - msm_dp_ctrl_set_psr(dp->ctrl, enter); + msm_dp_ctrl_set_psr(dp->ctrl, dp->panel, enter); } /** @@ -979,7 +979,7 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) } /* DP controller isr */ - ret |= msm_dp_ctrl_isr(dp->ctrl); + ret |= msm_dp_ctrl_isr(dp->ctrl, dp->panel); return ret; } From af6074252b7a178d2444edef5ea03d7cc7bbf77d Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:33 +0800 Subject: [PATCH 0736/1058] FROMLIST: drm/msm/dp: split dp_ctrl_off() into stream and link parts Split dp_ctrl_off() into stream and link parts so that for MST cases we can control the link and pixel parts separately. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-11-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 10 +++++----- drivers/gpu/drm/msm/dp/dp_ctrl.h | 5 +++-- drivers/gpu/drm/msm/dp/dp_display.c | 7 ++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 87c3a5517911f..90fba03de7f0b 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2211,7 +2211,7 @@ static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned l return ret; } -static void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; @@ -2240,7 +2240,8 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl * running. Add the global reset just before disabling the * link clocks and core clocks. */ - msm_dp_ctrl_off(&ctrl->msm_dp_ctrl, panel); + msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_off_link(&ctrl->msm_dp_ctrl, panel); ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl, panel); if (ret) { @@ -2634,8 +2635,8 @@ void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl) phy_init(phy); } -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl, - struct msm_dp_panel *panel) +void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; struct phy *phy; @@ -2649,7 +2650,6 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl, msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); - msm_dp_ctrl_off_pixel_clk(msm_dp_ctrl); dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 00b430392a52e..5902cf7e746a4 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -22,8 +22,9 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, bool force_link_train); -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl, - struct msm_dp_panel *panel); +void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 367d1d10af471..4f14bcee35772 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -725,15 +725,16 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) /* set dongle to D3 (power off) mode */ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); - msm_dp_ctrl_off(dp->ctrl, dp->panel); - /* re-init the PHY so that we can listen to Dongle disconnect */ + msm_dp_ctrl_off_pixel_clk(dp->ctrl); + msm_dp_ctrl_off_link(dp->ctrl, dp->panel); msm_dp_ctrl_reinit_phy(dp->ctrl); } else { /* * unplugged interrupt * dongle unplugged out of DUT */ - msm_dp_ctrl_off(dp->ctrl, dp->panel); + msm_dp_ctrl_off_pixel_clk(dp->ctrl); + msm_dp_ctrl_off_link(dp->ctrl, dp->panel); msm_dp_display_host_phy_exit(dp); } From d29f81d56f1c7478f0c623ee57a9d47becc4b677 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:34 +0800 Subject: [PATCH 0737/1058] FROMLIST: drm/msm/dp: simplify link and clock disable sequence Move the common disable steps out of the sink_count check to make the flow easier to follow. No functional change intended. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-12-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 4f14bcee35772..f1970e6dd7e46 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -716,27 +716,19 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) msm_dp_panel_disable_vsc_sdp(dp->panel); - /* dongle is still connected but sinks are disconnected */ - if (dp->link->sink_count == 0) { - /* - * irq_hpd with sink_count = 0 - * hdmi unplugged out of dongle - */ + msm_dp_ctrl_off_pixel_clk(dp->ctrl); - /* set dongle to D3 (power off) mode */ + /* dongle is still connected but sinks are disconnected */ + if (dp->link->sink_count == 0) msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); - msm_dp_ctrl_off_pixel_clk(dp->ctrl); - msm_dp_ctrl_off_link(dp->ctrl, dp->panel); + + msm_dp_ctrl_off_link(dp->ctrl, dp->panel); + + if (dp->link->sink_count == 0) + /* re-init the PHY so that we can listen to Dongle disconnect */ msm_dp_ctrl_reinit_phy(dp->ctrl); - } else { - /* - * unplugged interrupt - * dongle unplugged out of DUT - */ - msm_dp_ctrl_off_pixel_clk(dp->ctrl); - msm_dp_ctrl_off_link(dp->ctrl, dp->panel); + else msm_dp_display_host_phy_exit(dp); - } msm_dp_display->power_on = false; From 5f9c9892318db5393cc54a2967d91d6ef0317171 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:35 +0800 Subject: [PATCH 0738/1058] FROMLIST: drm/msm/dp: make bridge helpers use dp_display to allow re-use dp_bridge helpers take drm_bridge as an input and extract the dp_display object to be used in the dp_display module. Rather than doing it in a roundabout way, directly pass the dp_display object to these helpers so that the MST bridge can also re-use the same helpers. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-13-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 29 +++++++-------------- drivers/gpu/drm/msm/dp/dp_display.h | 7 ++++++ drivers/gpu/drm/msm/dp/dp_drm.c | 39 ++++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_drm.h | 9 ------- 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index f1970e6dd7e46..cdb7dd4cd7cbd 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -738,24 +738,21 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid - * @bridge: Pointer to drm bridge structure + * @dp: Pointer to dp display structure * @info: display info * @mode: Pointer to drm mode structure * Returns: Validity status for specified mode */ -enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) +enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { const u32 num_components = 3, default_bpp = 24; struct msm_dp_display_private *msm_dp_display; struct msm_dp_link_info *link_info; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; - struct msm_dp *dp; int mode_pclk_khz = mode->clock; - dp = to_dp_bridge(bridge)->msm_dp_display; - if (!dp || !mode_pclk_khz || !dp->connector) { DRM_ERROR("invalid params\n"); return -EINVAL; @@ -1406,11 +1403,9 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } -void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; int rc = 0; @@ -1419,7 +1414,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); crtc = drm_atomic_get_new_crtc_for_encoder(state, - drm_bridge->encoder); + msm_dp_display->bridge->encoder); if (!crtc) return; crtc_state = drm_atomic_get_new_crtc_state(state, crtc); @@ -1449,11 +1444,8 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } -void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_disable(struct msm_dp *dp) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); @@ -1470,11 +1462,8 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } -void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_post_disable(struct msm_dp *dp) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 0b65e16c790da..5116f7bbbd029 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -33,5 +33,12 @@ void msm_dp_display_signal_audio_start(struct msm_dp *msm_dp_display); void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display); void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp); +void msm_dp_display_atomic_post_disable(struct msm_dp *dp_display); +void msm_dp_display_atomic_disable(struct msm_dp *dp_display); +void msm_dp_display_atomic_enable(struct msm_dp *dp_display, + struct drm_atomic_commit *state); +enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, + const struct drm_display_info *info, + const struct drm_display_mode *mode); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 6ac5bac903d98..6b8923d9dff40 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -49,6 +49,43 @@ static void msm_dp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry msm_dp_display_debugfs_init(dp, root, false); } +static void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_enable(dp, state); +} + +static void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_disable(dp); +} + +static void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_post_disable(dp); +} + +static enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *drm_bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + return msm_dp_display_mode_valid(dp, info, mode); +} + static const struct drm_bridge_funcs msm_dp_bridge_ops = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, @@ -115,7 +152,7 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - msm_dp_bridge_atomic_enable(drm_bridge, state); + msm_dp_display_atomic_enable(dp, state); } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 4bd788ea05d5b..da412c788503c 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -27,15 +27,6 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector); -void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode); void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, From 97b4937aa4949810e8eb0ed25205e79a219dd5ce Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 9 Jun 2026 17:46:36 +0800 Subject: [PATCH 0739/1058] FROMLIST: drm/msm/dp: separate dp_display_prepare() into its own API For MST, the link setup should only be done once when multiple sinks are enabled, while stream setup may run multiple times for each sink. Split the link-related preparation out of msm_dp_display_atomic_enable() so it can be called separately before the per-stream enable path. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-14-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 16 +++++++++++----- drivers/gpu/drm/msm/dp/dp_display.h | 5 +++-- drivers/gpu/drm/msm/dp/dp_drm.c | 6 ++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index cdb7dd4cd7cbd..03320071fc077 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1403,8 +1403,8 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } -void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_prepare(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -1426,10 +1426,16 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, } rc = msm_dp_display_prepare_link(dp); - if (rc) { + if (rc) DRM_ERROR("DP display prepare failed, rc=%d\n", rc); - return; - } +} + +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + int rc = 0; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); rc = msm_dp_display_enable(dp); if (rc) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 5116f7bbbd029..43ed79093e241 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -35,8 +35,9 @@ void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp); void msm_dp_display_atomic_post_disable(struct msm_dp *dp_display); void msm_dp_display_atomic_disable(struct msm_dp *dp_display); -void msm_dp_display_atomic_enable(struct msm_dp *dp_display, - struct drm_atomic_commit *state); +void msm_dp_display_atomic_prepare(struct msm_dp *dp_display, + struct drm_atomic_commit *state); +void msm_dp_display_atomic_enable(struct msm_dp *dp_display); enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, const struct drm_display_info *info, const struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 6b8923d9dff40..4bf1a5b7c3f97 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -55,7 +55,8 @@ static void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = dp_bridge->msm_dp_display; - msm_dp_display_atomic_enable(dp, state); + msm_dp_display_atomic_prepare(dp, state); + msm_dp_display_atomic_enable(dp); } static void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, @@ -152,7 +153,8 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - msm_dp_display_atomic_enable(dp, state); + msm_dp_display_atomic_prepare(dp, state); + msm_dp_display_atomic_enable(dp); } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, From bb45f48db79a950b4ca97d5e7df581f1f87bea39 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Tue, 9 Jun 2026 17:46:37 +0800 Subject: [PATCH 0740/1058] FROMLIST: drm/msm/dp: pass panel to display enable/disable helpers Pass struct msm_dp_panel to the display enable/disable helpers to make them easier to reuse for MST stream handling. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260609-dp_mstclean-v7-15-ea04113e8233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 03320071fc077..888ecf34f1602 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -650,7 +650,8 @@ static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); } -static int msm_dp_display_enable(struct msm_dp_display_private *dp) +static int msm_dp_display_enable(struct msm_dp_display_private *dp, + struct msm_dp_panel *msm_dp_panel) { int rc = 0; struct msm_dp *msm_dp_display = &dp->msm_dp_display; @@ -661,7 +662,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp) return 0; } - rc = msm_dp_ctrl_on_stream(dp->ctrl, dp->panel); + rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel); if (!rc) msm_dp_display->power_on = true; @@ -707,20 +708,21 @@ static void msm_dp_display_audio_notify_disable(struct msm_dp_display_private *d msm_dp_display->audio_enabled = false; } -static int msm_dp_display_disable(struct msm_dp_display_private *dp) +static int msm_dp_display_disable(struct msm_dp_display_private *dp, + struct msm_dp_panel *msm_dp_panel) { struct msm_dp *msm_dp_display = &dp->msm_dp_display; if (!msm_dp_display->power_on) return 0; - msm_dp_panel_disable_vsc_sdp(dp->panel); + msm_dp_panel_disable_vsc_sdp(msm_dp_panel); msm_dp_ctrl_off_pixel_clk(dp->ctrl); /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) - msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); + msm_dp_link_psm_config(dp->link, &msm_dp_panel->link_info, true); msm_dp_ctrl_off_link(dp->ctrl, dp->panel); @@ -1437,14 +1439,14 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - rc = msm_dp_display_enable(dp); + rc = msm_dp_display_enable(dp, dp->panel); if (rc) DRM_ERROR("DP display enable failed, rc=%d\n", rc); rc = msm_dp_display_post_enable(msm_dp_display); if (rc) { DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(dp); + msm_dp_display_disable(dp, dp->panel); } drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); @@ -1479,7 +1481,7 @@ void msm_dp_display_atomic_post_disable(struct msm_dp *dp) msm_dp_display_audio_notify_disable(msm_dp_display); - msm_dp_display_disable(msm_dp_display); + msm_dp_display_disable(msm_dp_display, msm_dp_display->panel); msm_dp_display_unprepare(msm_dp_display); } From 1d36ee2db7f2a6f5058dd5537a287f6673147913 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:22 +0800 Subject: [PATCH 0741/1058] FROMLIST: drm/msm/dp: introduce stream_id for each DP panel With MST, each DP controller can handle multiple streams. There shall be one dp_panel for each stream but the dp_display object shall be shared among them. To represent this abstraction, create a stream_id for each DP panel which shall be dynamically assigned to actual stream IDs by the MST path. For SST, default this to stream 0. In the MST path, panels are dynamically assigned to actual stream IDs at stream enable time by the MST layer. Use the stream ID to control the pixel clock of that respective stream by extending the clock handles and state tracking of the DP pixel clock to an array of max supported streams. The maximum streams currently is 4. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-1-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 67 ++++++++++++++++++----------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_panel.c | 1 + drivers/gpu/drm/msm/dp/dp_panel.h | 11 +++++ 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 90fba03de7f0b..a475e787656eb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -126,7 +126,7 @@ struct msm_dp_ctrl_private { unsigned int num_link_clks; struct clk_bulk_data *link_clks; - struct clk *pixel_clk; + struct clk *pixel_clk[DP_STREAM_MAX]; union phy_configure_opts phy_opts; @@ -138,7 +138,7 @@ struct msm_dp_ctrl_private { bool core_clks_on; bool link_clks_on; - bool stream_clks_on; + bool stream_clks_on[DP_STREAM_MAX]; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -1746,7 +1746,7 @@ int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); @@ -1765,7 +1765,7 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); } @@ -1796,7 +1796,7 @@ static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); @@ -1815,7 +1815,7 @@ static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); } @@ -2188,38 +2188,39 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return success; } -static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate) +static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate, + enum msm_dp_stream_id stream_id) { int ret; - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); + ret = clk_set_rate(ctrl->pixel_clk[stream_id], pixel_rate * 1000); if (ret) { DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); return ret; } - if (WARN_ON_ONCE(ctrl->stream_clks_on)) + if (WARN_ON_ONCE(ctrl->stream_clks_on[stream_id])) return 0; - ret = clk_prepare_enable(ctrl->pixel_clk); + ret = clk_prepare_enable(ctrl->pixel_clk[stream_id]); if (ret) { DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); return ret; } - ctrl->stream_clks_on = true; + ctrl->stream_clks_on[stream_id] = true; return ret; } -void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id) { struct msm_dp_ctrl_private *ctrl; ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - if (ctrl->stream_clks_on) { - clk_disable_unprepare(ctrl->pixel_clk); - ctrl->stream_clks_on = false; + if (ctrl->stream_clks_on[stream_id]) { + clk_disable_unprepare(ctrl->pixel_clk[stream_id]); + ctrl->stream_clks_on[stream_id] = false; } } @@ -2240,7 +2241,7 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl * running. Add the global reset just before disabling the * link clocks and core clocks. */ - msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl, panel->stream_id); msm_dp_ctrl_off_link(&ctrl->msm_dp_ctrl, panel); ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl, panel); @@ -2250,7 +2251,7 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl } pixel_rate = panel->msm_dp_mode.drm_mode.clock; - ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate, panel->stream_id); msm_dp_ctrl_send_phy_test_pattern(ctrl); @@ -2542,9 +2543,8 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes); - drm_dbg_dp(ctrl->drm_dev, - "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", - ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); + drm_dbg_dp(ctrl->drm_dev, "core_clk_on=%d link_clk_on=%d\n", + ctrl->core_clks_on, ctrl->link_clks_on); if (!ctrl->link_clks_on) { /* link clk is off */ ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); @@ -2584,7 +2584,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * drm_dbg_dp(ctrl->drm_dev, "pixel_rate=%lu\n", pixel_rate); - ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate); + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate, panel->stream_id); if (ret) return ret; @@ -2644,8 +2644,6 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_panel_disable_vsc_sdp(panel); - msm_dp_ctrl_mainlink_disable(ctrl); msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); @@ -2716,6 +2714,13 @@ static const char *ctrl_clks[] = { "ctrl_link_iface", }; +static const char * const pixel_clks[] = { + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel", +}; + static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; @@ -2749,9 +2754,19 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) if (rc) return rc; - ctrl->pixel_clk = devm_clk_get(dev, "stream_pixel"); - if (IS_ERR(ctrl->pixel_clk)) - return PTR_ERR(ctrl->pixel_clk); + for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { + ctrl->pixel_clk[i] = devm_clk_get(dev, pixel_clks[i]); + + if (i == 0 && IS_ERR(ctrl->pixel_clk[i])) + return PTR_ERR(ctrl->pixel_clk[i]); + + if (IS_ERR(ctrl->pixel_clk[i])) { + if (PTR_ERR(ctrl->pixel_clk[i]) != -ENOENT) + return PTR_ERR(ctrl->pixel_clk[i]); + DRM_DEBUG_DP("stream %d pixel clock not found", i); + break; + } + } return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 5902cf7e746a4..be0d89d60914e 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -24,7 +24,7 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); -void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 888ecf34f1602..9306375e0c474 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -718,7 +718,7 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, msm_dp_panel_disable_vsc_sdp(msm_dp_panel); - msm_dp_ctrl_off_pixel_clk(dp->ctrl); + msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id); /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index e76dad0f66637..745ee69768979 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -723,6 +723,7 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux msm_dp_panel = &panel->msm_dp_panel; msm_dp_panel->max_bw_code = DP_LINK_BW_8_1; + msm_dp_panel->stream_id = DP_STREAM_0; return msm_dp_panel; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 4519ac3742206..50a7214017512 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -27,6 +27,15 @@ struct msm_dp_panel_psr { u8 capabilities; }; +/* stream id */ +enum msm_dp_stream_id { + DP_STREAM_0, + DP_STREAM_1, + DP_STREAM_2, + DP_STREAM_3, + DP_STREAM_MAX, +}; + struct msm_dp_panel { /* dpcd raw data */ u8 dpcd[DP_RECEIVER_CAP_SIZE]; @@ -40,6 +49,8 @@ struct msm_dp_panel { bool vsc_sdp_supported; u32 hw_revision; + enum msm_dp_stream_id stream_id; + u32 max_bw_code; }; From ed983f09ae1e41655a963da8f46555c48f2c3557 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:23 +0800 Subject: [PATCH 0742/1058] FROMLIST: drm/msm/dp: introduce max_streams for DP controller MST support DP controllers across different SoCs vary in the number of concurrent MST streams they can support. Rather than hardcoding per-platform values, the number of available pixel clocks in DT serves as a natural indicator since each stream requires a dedicated pixel clock. Introduce max_stream to capture this at initialization time and expose it for the MST module to use during setup. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-2-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 12 ++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 1 + 4 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index a475e787656eb..68fb4facb056b 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -127,6 +127,7 @@ struct msm_dp_ctrl_private { struct clk_bulk_data *link_clks; struct clk *pixel_clk[DP_STREAM_MAX]; + unsigned int num_pixel_clks; union phy_configure_opts phy_opts; @@ -2754,6 +2755,7 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) if (rc) return rc; + ctrl->num_pixel_clks = 0; for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { ctrl->pixel_clk[i] = devm_clk_get(dev, pixel_clks[i]); @@ -2766,11 +2768,22 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) DRM_DEBUG_DP("stream %d pixel clock not found", i); break; } + + ctrl->num_pixel_clks++; } return 0; } +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + return ctrl->num_pixel_clks; +} + struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, struct drm_dp_aux *aux, struct phy *phy, diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index be0d89d60914e..305add3dcd938 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -55,4 +55,5 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9306375e0c474..9190848f23220 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -87,6 +87,8 @@ struct msm_dp_display_private { void __iomem *p0_base; size_t p0_len; + + int max_stream; }; struct msm_dp_desc { @@ -578,6 +580,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) dp->ctrl = NULL; goto error_link; } + dp->max_stream = msm_dp_ctrl_get_stream_cnt(dp->ctrl); dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); if (IS_ERR(dp->audio)) { @@ -1178,6 +1181,15 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) return 0; } +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + return dp->max_stream; +} + static int msm_dp_display_probe(struct platform_device *pdev) { int rc = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 43ed79093e241..d3d4ab98089d5 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -26,6 +26,7 @@ struct msm_dp { bool psr_supported; }; +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display); int msm_dp_display_get_modes(struct msm_dp *msm_dp_display); bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display); int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display); From b9b578d7fe794356cb70a6831b14c243daf6e52e Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:24 +0800 Subject: [PATCH 0743/1058] FROMLIST: drm/msm/dp: Add support for programming p1/p2/p3 register blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for additional pixel register blocks (p1, p2, p3) to enable 4‑stream MST pixel clocks. Introduce the helper functions msm_dp_read_pn and msm_dp_write_pn for pixel register programming. All pixel clocks share the same register layout but use different base addresses. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-3-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 40 ++++++++++---- drivers/gpu/drm/msm/dp/dp_panel.c | 82 ++++++++++++++--------------- drivers/gpu/drm/msm/dp/dp_panel.h | 2 +- 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9190848f23220..dd159df9cce9e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -85,8 +85,8 @@ struct msm_dp_display_private { void __iomem *link_base; size_t link_len; - void __iomem *p0_base; - size_t p0_len; + void __iomem *pixel_base[DP_STREAM_MAX]; + size_t pixel_len; int max_stream; }; @@ -564,7 +564,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->p0_base); + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->pixel_base[0]); if (IS_ERR(dp->panel)) { rc = PTR_ERR(dp->panel); DRM_ERROR("failed to initialize panel, rc = %d\n", rc); @@ -850,8 +850,14 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) msm_dp_display->aux_base, "dp_aux"); msm_disp_snapshot_add_block(disp_state, msm_dp_display->link_len, msm_dp_display->link_base, "dp_link"); - msm_disp_snapshot_add_block(disp_state, msm_dp_display->p0_len, - msm_dp_display->p0_base, "dp_p0"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[0], "dp_p0"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[1], "dp_p1"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[2], "dp_p2"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[3], "dp_p3"); } void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter) @@ -1131,6 +1137,7 @@ static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_ static int msm_dp_display_get_io(struct msm_dp_display_private *display) { struct platform_device *pdev = display->msm_dp_display.pdev; + int i; display->ahb_base = msm_dp_ioremap(pdev, 0, &display->ahb_len); if (IS_ERR(display->ahb_base)) @@ -1160,8 +1167,8 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) display->aux_len = DP_DEFAULT_AUX_SIZE; display->link_base = display->ahb_base + DP_DEFAULT_LINK_OFFSET; display->link_len = DP_DEFAULT_LINK_SIZE; - display->p0_base = display->ahb_base + DP_DEFAULT_P0_OFFSET; - display->p0_len = DP_DEFAULT_P0_SIZE; + display->pixel_base[0] = display->ahb_base + DP_DEFAULT_P0_OFFSET; + display->pixel_len = DP_DEFAULT_P0_SIZE; return 0; } @@ -1172,10 +1179,21 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) return PTR_ERR(display->link_base); } - display->p0_base = msm_dp_ioremap(pdev, 3, &display->p0_len); - if (IS_ERR(display->p0_base)) { - DRM_ERROR("unable to remap p0 region: %pe\n", display->p0_base); - return PTR_ERR(display->p0_base); + display->pixel_base[0] = msm_dp_ioremap(pdev, 3, &display->pixel_len); + if (IS_ERR(display->pixel_base[0])) { + DRM_ERROR("unable to remap p0 region: %pe\n", display->pixel_base[0]); + return PTR_ERR(display->pixel_base[0]); + } + + for (i = DP_STREAM_1; i < DP_STREAM_MAX; i++) { + /* pixels clk reg index start from 3*/ + display->pixel_base[i] = msm_dp_ioremap(pdev, i + 3, &display->pixel_len); + if (IS_ERR(display->pixel_base[i])) { + DRM_DEBUG_DP("unable to remap p%d region: %pe\n", i, + display->pixel_base[i]); + display->pixel_base[i] = NULL; + break; + } } return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 745ee69768979..238920c452613 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -25,7 +25,7 @@ struct msm_dp_panel_private { struct drm_dp_aux *aux; struct msm_dp_link *link; void __iomem *link_base; - void __iomem *p0_base; + void __iomem *pixel_base; bool panel_on; }; @@ -44,24 +44,24 @@ static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, writel(data, panel->link_base + offset); } -static inline void msm_dp_write_p0(struct msm_dp_panel_private *panel, - u32 offset, u32 data) +static inline void msm_dp_write_pn(struct msm_dp_panel_private *panel, + u32 offset, u32 data) { /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, panel->p0_base + offset); + writel(data, panel->pixel_base + offset); } -static inline u32 msm_dp_read_p0(struct msm_dp_panel_private *panel, - u32 offset) +static inline u32 msm_dp_read_pn(struct msm_dp_panel_private *panel, + u32 offset) { /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(panel->p0_base + offset); + return readl_relaxed(panel->pixel_base + offset); } static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) @@ -367,34 +367,34 @@ static void msm_dp_panel_tpg_enable(struct msm_dp_panel *msm_dp_panel, display_hctl = (hsync_end_x << 16) | hsync_start_x; - msm_dp_write_p0(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * + msm_dp_write_pn(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * hsync_period); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0); - msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); - msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_POLARITY_CTL, 0); - - msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, - DP_TPG_CHECKERED_RECT_PATTERN); - msm_dp_write_p0(panel, MMSS_DP_TPG_VIDEO_CONFIG, - DP_TPG_VIDEO_CONFIG_BPP_8BIT | - DP_TPG_VIDEO_CONFIG_RGB); - msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, - DP_BIST_ENABLE_DPBIST_EN); - msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, - DP_TIMING_ENGINE_EN_EN); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0); + msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); + msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_POLARITY_CTL, 0); + + msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL, + DP_TPG_CHECKERED_RECT_PATTERN); + msm_dp_write_pn(panel, MMSS_DP_TPG_VIDEO_CONFIG, + DP_TPG_VIDEO_CONFIG_BPP_8BIT | + DP_TPG_VIDEO_CONFIG_RGB); + msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE, + DP_BIST_ENABLE_DPBIST_EN); + msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN, + DP_TIMING_ENGINE_EN_EN); drm_dbg_dp(panel->drm_dev, "%s: enabled tpg\n", __func__); } @@ -403,9 +403,9 @@ static void msm_dp_panel_tpg_disable(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel_private *panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0); - msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, 0x0); - msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0); + msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0); + msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE, 0x0); + msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0); } void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable) @@ -439,7 +439,7 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel_private *panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - msm_dp_write_p0(panel, MMSS_DP_DSC_DTO, 0x0); + msm_dp_write_pn(panel, MMSS_DP_DSC_DTO, 0x0); } static void msm_dp_panel_send_vsc_sdp(struct msm_dp_panel_private *panel, struct dp_sdp *vsc_sdp) @@ -629,7 +629,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) msm_dp_write_link(panel, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking); msm_dp_write_link(panel, REG_DP_ACTIVE_HOR_VER, msm_dp_active); - reg = msm_dp_read_p0(panel, MMSS_DP_INTF_CONFIG); + reg = msm_dp_read_pn(panel, MMSS_DP_INTF_CONFIG); if (wide_bus_en) reg |= DP_INTF_CONFIG_DATABUS_WIDEN; else @@ -637,7 +637,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) drm_dbg_dp(panel->drm_dev, "wide_bus_en=%d reg=%#x\n", wide_bus_en, reg); - msm_dp_write_p0(panel, MMSS_DP_INTF_CONFIG, reg); + msm_dp_write_pn(panel, MMSS_DP_INTF_CONFIG, reg); if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) msm_dp_panel_setup_vsc_sdp_yuv_420(msm_dp_panel); @@ -701,7 +701,7 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, - void __iomem *p0_base) + void __iomem *pixel_base) { struct msm_dp_panel_private *panel; struct msm_dp_panel *msm_dp_panel; @@ -719,7 +719,7 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux panel->aux = aux; panel->link = link; panel->link_base = link_base; - panel->p0_base = p0_base; + panel->pixel_base = pixel_base; msm_dp_panel = &panel->msm_dp_panel; msm_dp_panel->max_bw_code = DP_LINK_BW_8_1; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 50a7214017512..218a09a2fa655 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -102,5 +102,5 @@ static inline bool is_lane_count_valid(u32 lane_count) struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, - void __iomem *p0_base); + void __iomem *pixel_base); #endif /* _DP_PANEL_H_ */ From 2325f276a4e6ad6cee4c9ae8f29e103e79c2cb42 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:25 +0800 Subject: [PATCH 0744/1058] FROMLIST: drm/msm/dp: use stream_id to change offsets in dp_catalog In the DP MST architecture, stream 1 shares the same link clock as stream 0 but uses different register offsets within the same link register space. Use the dp_panel's stream_id to select the correct register offsets for stream 1 in dp_catalog. Also add stream 1 register defines. Streams 2 and 3 are not covered here, as they use separate link clocks and require separate handling. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-4-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 78 +++++++++++++++++++----- drivers/gpu/drm/msm/dp/dp_ctrl.h | 4 +- drivers/gpu/drm/msm/dp/dp_display.c | 24 +++++++- drivers/gpu/drm/msm/dp/dp_panel.c | 94 ++++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_panel.h | 4 ++ drivers/gpu/drm/msm/dp/dp_reg.h | 44 ++++++++++++++ 6 files changed, 229 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 68fb4facb056b..5c491a925b4b8 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -117,6 +117,8 @@ struct msm_dp_ctrl_private { struct msm_dp_link *link; void __iomem *ahb_base; void __iomem *link_base; + void __iomem *mst2link_base; + void __iomem *mst3link_base; struct phy *phy; @@ -172,6 +174,49 @@ static inline void msm_dp_write_link(struct msm_dp_ctrl_private *ctrl, writel(data, ctrl->link_base + offset); } +static inline u32 msm_dp_read_stream_link(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 offset) +{ + offset = msm_dp_stream_reg(stream_id, offset); + switch (stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + return readl_relaxed(ctrl->link_base + offset); + case DP_STREAM_2: + return readl_relaxed(ctrl->mst2link_base + offset); + case DP_STREAM_3: + return readl_relaxed(ctrl->mst3link_base + offset); + default: + DRM_ERROR("error stream_id\n"); + return 0; + } +} + +static inline void msm_dp_write_stream_link(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 offset, u32 data) +{ + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + offset = msm_dp_stream_reg(stream_id, offset); + switch (stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + writel(data, ctrl->link_base + offset); + break; + case DP_STREAM_2: + writel(data, ctrl->mst2link_base + offset); + break; + case DP_STREAM_3: + writel(data, ctrl->mst3link_base + offset); + break; + default: + DRM_ERROR("error stream_id\n"); + break; + } +} + static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, struct msm_dp_link_info *link) { @@ -397,7 +442,8 @@ static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, /* * RMW: Called from atomic_enable(). Serialized by the DRM atomic framework. */ - config = msm_dp_read_link(ctrl, REG_DP_CONFIGURATION_CTRL); + if (msm_dp_panel->stream_id == DP_STREAM_0) + config = msm_dp_read_link(ctrl, REG_DP_CONFIGURATION_CTRL); if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ @@ -412,7 +458,7 @@ static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, drm_dbg_dp(ctrl->drm_dev, "stream DP_CONFIGURATION_CTRL=0x%x\n", config); - msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_CONFIGURATION_CTRL, config); } static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl, @@ -469,7 +515,7 @@ static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, msm_dp_panel->msm_dp_mode.bpp); colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); - misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); + misc_val = msm_dp_read_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_MISC1_MISC0); /* clear bpp bits */ misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); @@ -479,7 +525,7 @@ static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, misc_val |= DP_MISC0_SYNCHRONOUS_CLK; drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); - msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_MISC1_MISC0, misc_val); } static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl, @@ -2461,8 +2507,8 @@ static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl, } static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, - u32 rate, u32 stream_rate_khz, - bool is_ycbcr_420) + struct msm_dp_panel *panel, + u32 rate, u32 stream_rate_khz) { u32 pixel_m, pixel_n; u32 mvid, nvid, pixel_div, dispcc_input_rate; @@ -2514,7 +2560,7 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, nvid = temp; } - if (is_ycbcr_420) + if (panel->msm_dp_mode.out_fmt_is_yuv_420) mvid /= 2; if (link_rate_hbr2 == rate) @@ -2524,8 +2570,8 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, nvid *= 3; drm_dbg_dp(ctrl->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid); - msm_dp_write_link(ctrl, REG_DP_SOFTWARE_MVID, mvid); - msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); + msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_MVID, mvid); + msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_NVID, nvid); } int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, @@ -2597,14 +2643,14 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_ctrl_lane_mapping(ctrl); msm_dp_setup_peripheral_flush(ctrl); - msm_dp_ctrl_config_ctrl_link(ctrl, panel); + if (panel->stream_id == DP_STREAM_0) + msm_dp_ctrl_config_ctrl_link(ctrl, panel); msm_dp_ctrl_configure_source_params(ctrl, panel); msm_dp_ctrl_config_msa(ctrl, - ctrl->link->link_params.rate, - pixel_rate_orig, - panel->msm_dp_mode.out_fmt_is_yuv_420); + panel, ctrl->link->link_params.rate, + pixel_rate_orig); msm_dp_panel_clear_dsc_dto(panel); @@ -2788,7 +2834,9 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, - void __iomem *link_base) + void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base) { struct msm_dp_ctrl_private *ctrl; int ret; @@ -2827,6 +2875,8 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link ctrl->phy = phy; ctrl->ahb_base = ahb_base; ctrl->link_base = link_base; + ctrl->mst2link_base = mst2link_base; + ctrl->mst3link_base = mst3link_base; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 305add3dcd938..49d16911ae8be 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -35,7 +35,9 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, - void __iomem *link_base); + void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base); void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index dd159df9cce9e..3b599b25f40cf 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -85,6 +85,12 @@ struct msm_dp_display_private { void __iomem *link_base; size_t link_len; + void __iomem *mst2link_base; + size_t mst2link_len; + + void __iomem *mst3link_base; + size_t mst3link_len; + void __iomem *pixel_base[DP_STREAM_MAX]; size_t pixel_len; @@ -564,7 +570,8 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->pixel_base[0]); + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, + dp->mst2link_base, dp->mst3link_base, dp->pixel_base[0]); if (IS_ERR(dp->panel)) { rc = PTR_ERR(dp->panel); DRM_ERROR("failed to initialize panel, rc = %d\n", rc); @@ -573,7 +580,8 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) } dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->aux, - phy, dp->ahb_base, dp->link_base); + phy, dp->ahb_base, dp->link_base, + dp->mst2link_base, dp->mst3link_base); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); @@ -850,6 +858,10 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) msm_dp_display->aux_base, "dp_aux"); msm_disp_snapshot_add_block(disp_state, msm_dp_display->link_len, msm_dp_display->link_base, "dp_link"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->mst2link_len, + msm_dp_display->mst2link_base, "dp_mst2link"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->mst3link_len, + msm_dp_display->mst3link_base, "dp_mst3link"); msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, msm_dp_display->pixel_base[0], "dp_p0"); msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, @@ -1196,6 +1208,14 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) } } + display->mst2link_base = msm_dp_ioremap(pdev, 7, &display->mst2link_len); + if (IS_ERR(display->mst2link_base)) + DRM_DEBUG_DP("unable to remap link region: %pe\n", display->mst2link_base); + + display->mst3link_base = msm_dp_ioremap(pdev, 8, &display->mst3link_len); + if (IS_ERR(display->mst3link_base)) + DRM_DEBUG_DP("unable to remap link region: %pe\n", display->mst3link_base); + return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 238920c452613..e0c0e8c9178c8 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -25,13 +25,84 @@ struct msm_dp_panel_private { struct drm_dp_aux *aux; struct msm_dp_link *link; void __iomem *link_base; + void __iomem *mst2link_base; + void __iomem *mst3link_base; void __iomem *pixel_base; bool panel_on; }; +u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg) +{ + bool is_s1 = (id == DP_STREAM_1); + + if (id == DP_STREAM_0) + return reg; + + switch (reg) { + case REG_DP_CONFIGURATION_CTRL: + return is_s1 ? REG_DP1_CONFIGURATION_CTRL : REG_DP_MSTLINK_CONFIGURATION_CTRL; + case REG_DP_SOFTWARE_MVID: + return is_s1 ? REG_DP1_SOFTWARE_MVID : REG_MSTLINK_SOFTWARE_MVID; + case REG_DP_SOFTWARE_NVID: + return is_s1 ? REG_DP1_SOFTWARE_NVID : REG_MSTLINK_SOFTWARE_NVID; + case REG_DP_TOTAL_HOR_VER: + return is_s1 ? REG_DP1_TOTAL_HOR_VER : REG_DP_MSTLINK_TOTAL_HOR_VER; + case REG_DP_START_HOR_VER_FROM_SYNC: + return is_s1 ? REG_DP1_START_HOR_VER_FROM_SYNC + : REG_DP_MSTLINK_START_HOR_VER_FROM_SYNC; + case REG_DP_HSYNC_VSYNC_WIDTH_POLARITY: + return is_s1 ? REG_DP1_HSYNC_VSYNC_WIDTH_POLARITY + : REG_DP_MSTLINK_HSYNC_VSYNC_WIDTH_POLARITY; + case REG_DP_ACTIVE_HOR_VER: + return is_s1 ? REG_DP1_ACTIVE_HOR_VER : REG_DP_MSTLINK_ACTIVE_HOR_VER; + case REG_DP_MISC1_MISC0: + return is_s1 ? REG_DP1_MISC1_MISC0 : REG_DP_MSTLINK_MISC1_MISC0; + case MMSS_DP_SDP_CFG: + return is_s1 ? MMSS_DP1_SDP_CFG : MMSS_DP_MSTLINK_SDP_CFG; + case MMSS_DP_SDP_CFG2: + return is_s1 ? MMSS_DP1_SDP_CFG2 : MMSS_DP_MSTLINK_SDP_CFG2; + case MMSS_DP_SDP_CFG3: + return is_s1 ? MMSS_DP1_SDP_CFG3 : MMSS_DP_MSTLINK_SDP_CFG3; + case MMSS_DP_GENERIC0_0: + return is_s1 ? MMSS_DP1_GENERIC0_0 : MMSS_DP_MSTLINK_GENERIC0_0; + case MMSS_DP_GENERIC0_1: + return is_s1 ? MMSS_DP1_GENERIC0_1 : MMSS_DP_MSTLINK_GENERIC0_1; + case MMSS_DP_GENERIC0_2: + return is_s1 ? MMSS_DP1_GENERIC0_2 : MMSS_DP_MSTLINK_GENERIC0_2; + case MMSS_DP_GENERIC0_3: + return is_s1 ? MMSS_DP1_GENERIC0_3 : MMSS_DP_MSTLINK_GENERIC0_3; + case MMSS_DP_GENERIC0_4: + return is_s1 ? MMSS_DP1_GENERIC0_4 : MMSS_DP_MSTLINK_GENERIC0_4; + case MMSS_DP_GENERIC0_5: + return is_s1 ? MMSS_DP1_GENERIC0_5 : MMSS_DP_MSTLINK_GENERIC0_5; + case MMSS_DP_GENERIC0_6: + return is_s1 ? MMSS_DP1_GENERIC0_6 : MMSS_DP_MSTLINK_GENERIC0_6; + case MMSS_DP_GENERIC0_7: + return is_s1 ? MMSS_DP1_GENERIC0_7 : MMSS_DP_MSTLINK_GENERIC0_7; + case MMSS_DP_GENERIC0_8: + return is_s1 ? MMSS_DP1_GENERIC0_8 : MMSS_DP_MSTLINK_GENERIC0_8; + case MMSS_DP_GENERIC0_9: + return is_s1 ? MMSS_DP1_GENERIC0_9 : MMSS_DP_MSTLINK_GENERIC0_9; + default: + return reg; + } +} + static inline u32 msm_dp_read_link(struct msm_dp_panel_private *panel, u32 offset) { - return readl_relaxed(panel->link_base + offset); + offset = msm_dp_stream_reg(panel->msm_dp_panel.stream_id, offset); + switch (panel->msm_dp_panel.stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + return readl_relaxed(panel->link_base + offset); + case DP_STREAM_2: + return readl_relaxed(panel->mst2link_base + offset); + case DP_STREAM_3: + return readl_relaxed(panel->mst3link_base + offset); + default: + DRM_ERROR("error stream_id\n"); + return 0; + } } static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, @@ -41,7 +112,22 @@ static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, * To make sure link reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, panel->link_base + offset); + offset = msm_dp_stream_reg(panel->msm_dp_panel.stream_id, offset); + switch (panel->msm_dp_panel.stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + writel(data, panel->link_base + offset); + break; + case DP_STREAM_2: + writel(data, panel->mst2link_base + offset); + break; + case DP_STREAM_3: + writel(data, panel->mst3link_base + offset); + break; + default: + DRM_ERROR("error stream_id\n"); + break; + } } static inline void msm_dp_write_pn(struct msm_dp_panel_private *panel, @@ -701,6 +787,8 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base, void __iomem *pixel_base) { struct msm_dp_panel_private *panel; @@ -720,6 +808,8 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux panel->link = link; panel->link_base = link_base; panel->pixel_base = pixel_base; + panel->mst2link_base = mst2link_base; + panel->mst3link_base = mst3link_base; msm_dp_panel = &panel->msm_dp_panel; msm_dp_panel->max_bw_code = DP_LINK_BW_8_1; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 218a09a2fa655..dc046fec24fc7 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -99,8 +99,12 @@ static inline bool is_lane_count_valid(u32 lane_count) lane_count == 4); } +u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg); + struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base, void __iomem *pixel_base); #endif /* _DP_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 3689642b7fc06..310e5a1cc934a 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -332,6 +332,50 @@ #define DP_TPG_VIDEO_CONFIG_BPP_8BIT (0x00000001) #define DP_TPG_VIDEO_CONFIG_RGB (0x00000004) +#define REG_DP1_CONFIGURATION_CTRL (0x00000400) +#define REG_DP1_SOFTWARE_MVID (0x00000414) +#define REG_DP1_SOFTWARE_NVID (0x00000418) +#define REG_DP1_TOTAL_HOR_VER (0x0000041C) +#define REG_DP1_START_HOR_VER_FROM_SYNC (0x00000420) +#define REG_DP1_HSYNC_VSYNC_WIDTH_POLARITY (0x00000424) +#define REG_DP1_ACTIVE_HOR_VER (0x00000428) +#define REG_DP1_MISC1_MISC0 (0x0000042C) +#define MMSS_DP1_GENERIC0_0 (0x00000490) +#define MMSS_DP1_GENERIC0_1 (0x00000494) +#define MMSS_DP1_GENERIC0_2 (0x00000498) +#define MMSS_DP1_GENERIC0_3 (0x0000049C) +#define MMSS_DP1_GENERIC0_4 (0x000004A0) +#define MMSS_DP1_GENERIC0_5 (0x000004A4) +#define MMSS_DP1_GENERIC0_6 (0x000004A8) +#define MMSS_DP1_GENERIC0_7 (0x000004AC) +#define MMSS_DP1_GENERIC0_8 (0x000004B0) +#define MMSS_DP1_GENERIC0_9 (0x000004B4) +#define MMSS_DP1_SDP_CFG (0x000004E0) +#define MMSS_DP1_SDP_CFG2 (0x000004E4) +#define MMSS_DP1_SDP_CFG3 (0x000004E8) + +#define REG_DP_MSTLINK_CONFIGURATION_CTRL (0x00000034) +#define REG_MSTLINK_SOFTWARE_MVID (0x00000040) +#define REG_MSTLINK_SOFTWARE_NVID (0x00000044) +#define REG_DP_MSTLINK_TOTAL_HOR_VER (0x00000048) +#define REG_DP_MSTLINK_START_HOR_VER_FROM_SYNC (0x0000004C) +#define REG_DP_MSTLINK_HSYNC_VSYNC_WIDTH_POLARITY (0x00000050) +#define REG_DP_MSTLINK_ACTIVE_HOR_VER (0x00000054) +#define REG_DP_MSTLINK_MISC1_MISC0 (0x00000058) +#define MMSS_DP_MSTLINK_GENERIC0_0 (0x000000BC) +#define MMSS_DP_MSTLINK_GENERIC0_1 (0x000000C0) +#define MMSS_DP_MSTLINK_GENERIC0_2 (0x000000C4) +#define MMSS_DP_MSTLINK_GENERIC0_3 (0x000000C8) +#define MMSS_DP_MSTLINK_GENERIC0_4 (0x000000CC) +#define MMSS_DP_MSTLINK_GENERIC0_5 (0x000000D0) +#define MMSS_DP_MSTLINK_GENERIC0_6 (0x000000D4) +#define MMSS_DP_MSTLINK_GENERIC0_7 (0x000000D8) +#define MMSS_DP_MSTLINK_GENERIC0_8 (0x000000DC) +#define MMSS_DP_MSTLINK_GENERIC0_9 (0x000000E0) +#define MMSS_DP_MSTLINK_SDP_CFG (0x0000010c) +#define MMSS_DP_MSTLINK_SDP_CFG2 (0x0000011c) +#define MMSS_DP_MSTLINK_SDP_CFG3 (0x00000114) + #define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000088) #define REG_DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C) From 64bea1372ff5d45f6c122c793fe428c50f3cb69a Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:26 +0800 Subject: [PATCH 0745/1058] FROMLIST: drm/msm/dp: add support to send ACT packets for MST Whenever virtual channel slot allocation changes, the DP source must send the action control trigger sequence to notify the sink about the same. This would be applicable during the start and stop of the pixel stream. Add the infrastructure to be able to send ACT packets for the DP controller when operating in MST mode. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-5-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 44 ++++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_ctrl.h | 5 +++- drivers/gpu/drm/msm/dp/dp_display.c | 3 +- drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_reg.h | 2 ++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 5c491a925b4b8..6754b10d418cf 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -142,6 +142,7 @@ struct msm_dp_ctrl_private { bool core_clks_on; bool link_clks_on; bool stream_clks_on[DP_STREAM_MAX]; + bool mst_active; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -244,6 +245,37 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, return err; } +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) +{ + struct msm_dp_ctrl_private *ctrl; + const struct drm_display_mode *mode; + u32 frame_time_ms; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return 0; + + mode = &panel->msm_dp_mode.drm_mode; + frame_time_ms = DIV_ROUND_UP((u64)mode->htotal * mode->vtotal, + mode->clock) + 1; + + msm_dp_write_link(ctrl, REG_DP_MST_ACT, 0x1); + /* make sure ACT signal is performed */ + wmb(); + + msleep(frame_time_ms); + + /* Hardware clears this bit after sending 4 ACT headers */ + if (msm_dp_read_link(ctrl, REG_DP_MST_ACT)) { + drm_dbg_dp(ctrl->drm_dev, "MST ACT trigger complete failed\n"); + return -EINVAL; + } + + return 0; +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2610,7 +2642,8 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, return ret; } -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active) { int ret = 0; bool mainlink_ready = false; @@ -2623,6 +2656,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + ctrl->mst_active = mst_active; + pixel_rate_orig = panel->msm_dp_mode.drm_mode.clock; pixel_rate = pixel_rate_orig; @@ -2658,6 +2693,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); + ret = msm_dp_ctrl_mst_send_act(msm_dp_ctrl, panel); + if (ret) + return ret; + ret = msm_dp_ctrl_wait4video_ready(ctrl); if (ret) return ret; @@ -2695,6 +2734,8 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); + ctrl->mst_active = false; + dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); @@ -2877,6 +2918,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link ctrl->link_base = link_base; ctrl->mst2link_base = mst2link_base; ctrl->mst3link_base = mst3link_base; + ctrl->mst_active = false; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 49d16911ae8be..6de028da85fb9 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -18,7 +18,8 @@ struct phy; int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active); int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, bool force_link_train); @@ -58,4 +59,6 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl); +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 3b599b25f40cf..ad848211096ec 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -673,7 +673,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, return 0; } - rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel); + rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active); if (!rc) msm_dp_display->power_on = true; @@ -1509,6 +1509,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index d3d4ab98089d5..e987de80522c3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -19,6 +19,7 @@ struct msm_dp { struct drm_bridge *bridge; bool audio_enabled; bool power_on; + bool mst_active; unsigned int connector_type; bool is_edp; diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 310e5a1cc934a..6808965878d45 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -156,6 +156,8 @@ #define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) #define DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT (0x0D) +#define REG_DP_MST_ACT (0x00000500) + #define REG_DP_SOFTWARE_MVID (0x00000010) #define REG_DP_SOFTWARE_NVID (0x00000018) #define REG_DP_TOTAL_HOR_VER (0x0000001C) From 27841c8351c7d065d5d14dcdff2b225a8edfdc27 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:27 +0800 Subject: [PATCH 0746/1058] FROMLIST: drm/msm/dp: Add support to enable MST in mainlink control Add support to program the MST enable bit in the mainlink control register when an MST session is active or being disabled. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-6-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 17 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_reg.h | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 6754b10d418cf..e9aa0e254234a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -276,6 +276,19 @@ int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, return 0; } +static void msm_dp_ctrl_mst_config(struct msm_dp_ctrl_private *ctrl, bool enable) +{ + u32 mainlink_ctrl; + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + if (enable) + mainlink_ctrl |= DP_MAINLINK_CTRL_MST_EN; + else + mainlink_ctrl &= ~DP_MAINLINK_CTRL_MST_EN; + + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2678,6 +2691,9 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_ctrl_lane_mapping(ctrl); msm_dp_setup_peripheral_flush(ctrl); + if (ctrl->mst_active) + msm_dp_ctrl_mst_config(ctrl, true); + if (panel->stream_id == DP_STREAM_0) msm_dp_ctrl_config_ctrl_link(ctrl, panel); @@ -2731,6 +2747,7 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, phy = ctrl->phy; msm_dp_ctrl_mainlink_disable(ctrl); + msm_dp_ctrl_mst_config(ctrl, false); msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 6808965878d45..deb40ed246549 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -128,6 +128,10 @@ #define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 1) #define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 3) #define DP_MAINLINK_FB_BOUNDARY_SEL (0x02000000) +#define DP_MAINLINK_CTRL_ECF_MODE BIT(26) +#define DP_MAINLINK_CTRL_MST_ACTIVE BIT(8) +#define DP_MAINLINK_CTRL_MST_EN (DP_MAINLINK_CTRL_ECF_MODE | \ + DP_MAINLINK_CTRL_MST_ACTIVE) #define REG_DP_STATE_CTRL (0x00000004) #define DP_STATE_CTRL_LINK_TRAINING_PATTERN1 (0x00000001) From b2b983dea8db257ec155a18cc0cce656c7aca045 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:28 +0800 Subject: [PATCH 0747/1058] FROMLIST: drm/msm/dp: no need to update tu calculation for mst DP stream is transmitted in transfer units only for SST case, there is no need to calculate and program TU parameters for MST case. Skip the TU programming for MST cases. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-7-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index e9aa0e254234a..5b5149b160df1 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2705,7 +2705,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_panel_clear_dsc_dto(panel); - msm_dp_ctrl_setup_tr_unit(ctrl, panel); + if (!ctrl->mst_active) + msm_dp_ctrl_setup_tr_unit(ctrl, panel); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); From f41ac5a372f574a4c64d8a6321af986a7737d01b Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:29 +0800 Subject: [PATCH 0748/1058] FROMLIST: drm/msm/dp: Add support for MST channel slot allocation DP MST streams share 64 MTP slots in a time-multiplexed manner. Add support for calculating the rate governor, slot allocation, and slot reservation in the DP controller. Each MST stream can reserve its slots by calling msm_dp_display_set_stream_info() from its bridge callbacks. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-8-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 192 ++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 4 + drivers/gpu/drm/msm/dp/dp_display.c | 17 +++ drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_panel.c | 6 + drivers/gpu/drm/msm/dp/dp_panel.h | 1 + drivers/gpu/drm/msm/dp/dp_reg.h | 10 ++ 7 files changed, 232 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 5b5149b160df1..15df82a0caca9 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -73,6 +73,7 @@ #define MR_LINK_PRBS7 0x100 #define MR_LINK_CUSTOM80 0x200 #define MR_LINK_TRAINING4 0x40 +#define DP_MAX_TIME_SLOTS 64 enum { DP_TRAINING_NONE, @@ -109,6 +110,11 @@ struct msm_dp_vc_tu_mapping_table { u8 tu_size_minus1; }; +struct msm_dp_mst_ch_slot_info { + u32 start_slot; + u32 tot_slots; +}; + struct msm_dp_ctrl_private { struct msm_dp_ctrl msm_dp_ctrl; struct drm_device *drm_dev; @@ -143,6 +149,8 @@ struct msm_dp_ctrl_private { bool link_clks_on; bool stream_clks_on[DP_STREAM_MAX]; bool mst_active; + + struct msm_dp_mst_ch_slot_info mst_ch_info[DP_STREAM_MAX]; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -289,6 +297,44 @@ static void msm_dp_ctrl_mst_config(struct msm_dp_ctrl_private *ctrl, bool enable msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); } +static void msm_dp_ctrl_mst_channel_alloc(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 ch_start_slot, + u32 tot_slot_cnt) +{ + u32 slot_reg_1 = 0, slot_reg_2 = 0; + + if (ch_start_slot > DP_MAX_TIME_SLOTS || + (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { + DRM_ERROR("invalid slots start %d, tot %d\n", + ch_start_slot, tot_slot_cnt); + return; + } + + drm_dbg_dp(ctrl->drm_dev, "stream_id %d, start_slot %d, tot_slot %d\n", + stream_id, ch_start_slot, tot_slot_cnt); + + if (ch_start_slot && tot_slot_cnt) { + u64 mask = GENMASK_ULL(ch_start_slot + tot_slot_cnt - 2, ch_start_slot - 1); + + slot_reg_1 = mask & 0xFFFFFFFF; + slot_reg_2 = (mask >> 32) & 0xFFFFFFFF; + } + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_1_32, slot_reg_1); + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_33_63, slot_reg_2); +} + +static void msm_dp_ctrl_update_rg(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 x_int, u32 y_frac_enum) +{ + u32 rg = y_frac_enum | (x_int << 16); + + drm_dbg_dp(ctrl->drm_dev, "stream_id: %d x_int:%d y_frac_enum:%d rg:%d\n", + stream_id, x_int, y_frac_enum, rg); + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_RG, rg); +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2619,6 +2665,117 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_NVID, nvid); } +/* + * Calculate MST Rate Governor parameters x_int and y_frac_enum (HPG 3.8.1.2). + * + * The RG paces symbol delivery per MTP via: M = x_int + y_frac_enum/256 + * where M is the target symbol count per MTP across all lanes. + * + * min_slot_cnt = (pclk * bpp/8) / (lclk * lanes) * 64 -- slots at 1.0x BW + * max_slot_cnt = pbn * 54 / (lclk * lanes) -- slots at PBN limit + * raw_target_sc = (min + max) / 2 -- midpoint (~1.003x) + * + * Quantize raw_target_sc to 1/(256*lanes) steps, then: + * M = Chosen_TARGET_Slot_Count * lanes + * x_int = INT(M) + * y_frac_enum = CEIL(256 * MOD(M, 1)) + */ +static void msm_dp_ctrl_mst_calculate_rg(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, + u32 *p_x_int, u32 *p_y_frac_enum) +{ + u64 min_slot_cnt, max_slot_cnt; + u64 raw_target_sc, target_sc_fixp; + u64 ts_denom, ts_enum, ts_int; + u64 pclk = panel->msm_dp_mode.drm_mode.clock; + u64 lclk = 0; + u64 lanes = ctrl->link->link_params.num_lanes; + u64 bpp = panel->msm_dp_mode.bpp; + u64 pbn = panel->pbn; + u64 numerator, denominator, temp, temp1, temp2; + u32 x_int = 0, y_frac_enum = 0; + u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; + + lclk = ctrl->link->link_params.rate; + + /* min_slot_cnt */ + numerator = pclk * bpp * 64 * 1000; + denominator = lclk * lanes * 8 * 1000; + min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* max_slot_cnt */ + numerator = pbn * 54 * 1000; + denominator = lclk * lanes; + max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* raw_target_sc */ + numerator = max_slot_cnt + min_slot_cnt; + denominator = drm_fixp_from_fraction(2, 1); + raw_target_sc = drm_fixp_div(numerator, denominator); + + /* target_sc */ + temp = drm_fixp_from_fraction(256 * lanes, 1); + numerator = drm_fixp_mul(raw_target_sc, temp); + denominator = drm_fixp_from_fraction(256 * lanes, 1); + target_sc_fixp = drm_fixp_div(numerator, denominator); + + ts_enum = 256 * lanes; + ts_denom = drm_fixp_from_fraction(256 * lanes, 1); + ts_int = drm_fixp2int(target_sc_fixp); + + temp = drm_fixp2int_ceil(raw_target_sc); + if (temp != ts_int) { + temp = drm_fixp_from_fraction(ts_int, 1); + temp1 = raw_target_sc - temp; + temp2 = drm_fixp_mul(temp1, ts_denom); + ts_enum = drm_fixp2int(temp2); + } + + /* target_strm_sym */ + ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); + ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); + temp = ts_int_fixp + ts_frac_fixp; + temp1 = drm_fixp_from_fraction(lanes, 1); + target_strm_sym = drm_fixp_mul(temp, temp1); + + /* x_int */ + x_int = drm_fixp2int(target_strm_sym); + + /* y_enum_frac */ + temp = drm_fixp_from_fraction(x_int, 1); + temp1 = target_strm_sym - temp; + temp2 = drm_fixp_from_fraction(256, 1); + y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); + + temp1 = drm_fixp2int(y_frac_enum_fixp); + temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); + + y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); + + *p_x_int = x_int; + *p_y_frac_enum = y_frac_enum; + + drm_dbg_dp(ctrl->drm_dev, "MST lane_cnt:%llu, rate:%llu x_int:%d, y_frac:%d\n", + lanes, lclk, x_int, y_frac_enum); +} + +static void msm_dp_ctrl_mst_stream_setup(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) +{ + u32 x_int, y_frac_enum; + + if (!ctrl->mst_active) + return; + + drm_dbg_dp(ctrl->drm_dev, "MST stream channel allocation\n"); + + msm_dp_ctrl_mst_stream_channel_slot_setup(&ctrl->msm_dp_ctrl); + + msm_dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); + + msm_dp_ctrl_update_rg(ctrl, panel->stream_id, x_int, y_frac_enum); +} + int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, bool force_link_train) @@ -2708,6 +2865,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * if (!ctrl->mst_active) msm_dp_ctrl_setup_tr_unit(ctrl, panel); + msm_dp_ctrl_mst_stream_setup(ctrl, panel); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); ret = msm_dp_ctrl_mst_send_act(msm_dp_ctrl, panel); @@ -2760,6 +2919,39 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, phy_power_off(phy); } +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots) +{ + struct msm_dp_ctrl_private *ctrl; + + if (!msm_dp_ctrl || stream_id >= DP_STREAM_MAX) { + DRM_ERROR("invalid input\n"); + return; + } + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + ctrl->mst_ch_info[stream_id].start_slot = start_slot; + ctrl->mst_ch_info[stream_id].tot_slots = tot_slots; +} + +void msm_dp_ctrl_mst_stream_channel_slot_setup(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + int i; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return; + + for (i = DP_STREAM_0; i < ctrl->num_pixel_clks; i++) { + msm_dp_ctrl_mst_channel_alloc(ctrl, i, ctrl->mst_ch_info[i].start_slot, + ctrl->mst_ch_info[i].tot_slots); + } +} + irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 6de028da85fb9..e1d10ae20f705 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -61,4 +61,8 @@ void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl); int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +void msm_dp_ctrl_mst_stream_channel_slot_setup(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ad848211096ec..dccd3df368593 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -749,6 +749,20 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, return 0; } +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_ctrl_set_mst_channel_info(dp->ctrl, panel->stream_id, start_slot, num_slots); + + panel->pbn = pbn; + + return 0; +} + /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid * @dp: Pointer to dp display structure @@ -1489,6 +1503,8 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + msm_dp_display_set_stream_info(msm_dp_display, dp->panel, 0, 0, 0); + rc = msm_dp_display_enable(dp, dp->panel); if (rc) DRM_ERROR("DP display enable failed, rc=%d\n", rc); @@ -1509,6 +1525,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_ctrl_mst_stream_channel_slot_setup(msm_dp_display->ctrl); msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index e987de80522c3..45e2cc2d6adda 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -43,5 +43,7 @@ void msm_dp_display_atomic_enable(struct msm_dp *dp_display); enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, const struct drm_display_info *info, const struct drm_display_mode *mode); +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index e0c0e8c9178c8..ef2ded8ec4ea5 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -57,6 +57,12 @@ u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg) return is_s1 ? REG_DP1_ACTIVE_HOR_VER : REG_DP_MSTLINK_ACTIVE_HOR_VER; case REG_DP_MISC1_MISC0: return is_s1 ? REG_DP1_MISC1_MISC0 : REG_DP_MSTLINK_MISC1_MISC0; + case REG_DP_DP0_TIMESLOT_1_32: + return is_s1 ? REG_DP_DP1_TIMESLOT_1_32 : REG_DP_MSTLINK_TIMESLOT_1_32; + case REG_DP_DP0_TIMESLOT_33_63: + return is_s1 ? REG_DP_DP1_TIMESLOT_33_63 : REG_DP_MSTLINK_TIMESLOT_33_63; + case REG_DP_DP0_RG: + return is_s1 ? REG_DP_DP1_RG : REG_DP_MSTLINK_DP_RG; case MMSS_DP_SDP_CFG: return is_s1 ? MMSS_DP1_SDP_CFG : MMSS_DP_MSTLINK_SDP_CFG; case MMSS_DP_SDP_CFG2: diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index dc046fec24fc7..3e78af9e430dc 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -50,6 +50,7 @@ struct msm_dp_panel { u32 hw_revision; enum msm_dp_stream_id stream_id; + u32 pbn; u32 max_bw_code; }; diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index deb40ed246549..f2bd96f3bbd01 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -338,7 +338,13 @@ #define DP_TPG_VIDEO_CONFIG_BPP_8BIT (0x00000001) #define DP_TPG_VIDEO_CONFIG_RGB (0x00000004) + +#define REG_DP_MSTLINK_DP_RG (0X0000011C) #define REG_DP1_CONFIGURATION_CTRL (0x00000400) +#define REG_DP_DP0_TIMESLOT_1_32 (0x00000404) +#define REG_DP_DP0_TIMESLOT_33_63 (0x00000408) +#define REG_DP_DP1_TIMESLOT_1_32 (0x0000040C) +#define REG_DP_DP1_TIMESLOT_33_63 (0x00000410) #define REG_DP1_SOFTWARE_MVID (0x00000414) #define REG_DP1_SOFTWARE_NVID (0x00000418) #define REG_DP1_TOTAL_HOR_VER (0x0000041C) @@ -359,8 +365,12 @@ #define MMSS_DP1_SDP_CFG (0x000004E0) #define MMSS_DP1_SDP_CFG2 (0x000004E4) #define MMSS_DP1_SDP_CFG3 (0x000004E8) +#define REG_DP_DP0_RG (0x000004F8) +#define REG_DP_DP1_RG (0x000004FC) #define REG_DP_MSTLINK_CONFIGURATION_CTRL (0x00000034) +#define REG_DP_MSTLINK_TIMESLOT_1_32 (0x00000038) +#define REG_DP_MSTLINK_TIMESLOT_33_63 (0x0000003C) #define REG_MSTLINK_SOFTWARE_MVID (0x00000040) #define REG_MSTLINK_SOFTWARE_NVID (0x00000044) #define REG_DP_MSTLINK_TOTAL_HOR_VER (0x00000048) From ea2f75eea15a8c937aa155bfa3f8f201e4d992b6 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:30 +0800 Subject: [PATCH 0749/1058] FROMLIST: drm/msm/dp: Add support for sending VCPF packets in DP controller The VC Payload Fill (VCPF) sequence is inserted by the DP controller when stream symbols are absent, typically before a stream is disabled. Add support for triggering the VCPF sequence in the MSM DP controller. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-9-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 57 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_panel.c | 2 + drivers/gpu/drm/msm/dp/dp_reg.h | 8 ++++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 15df82a0caca9..c4f1a68b1210c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -65,6 +65,11 @@ (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) +#define DP_INTERRUPT_STATUS5 \ + (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT) +#define DP_INTERRUPT_STATUS5_MASK \ + (DP_INTERRUPT_STATUS5 << DP_INTERRUPT_STATUS_MASK_SHIFT) + #define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) #define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) @@ -398,6 +403,8 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl) DP_INTERRUPT_STATUS1_MASK); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, DP_INTERRUPT_STATUS2_MASK); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + DP_INTERRUPT_STATUS5_MASK); } void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) @@ -407,6 +414,7 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, 0x00); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, 0x00); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, 0x00); } static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl) @@ -426,6 +434,20 @@ static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4); } +static u32 msm_dp_ctrl_get_mst_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS5); + intr &= ~DP_INTERRUPT_STATUS5_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS5) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + intr_ack | DP_INTERRUPT_STATUS5_MASK); + + return intr; +} + static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl) { u32 val; @@ -525,6 +547,34 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); } +/* Must be called with msm_dp_mst::mst_lock held */ +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_ctrl_private *ctrl; + u32 state = 0x0; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + state |= DP_STATE_CTRL_PUSH_IDLE; + else if (msm_dp_panel->stream_id == DP_STREAM_0) + state |= DP_DP0_PUSH_VCPF; + else if (msm_dp_panel->stream_id == DP_STREAM_1) + state |= DP_DP1_PUSH_VCPF; + else + state |= DP_MSTLINK_PUSH_VCPF; + + reinit_completion(&ctrl->idle_comp); + + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_STATE_CTRL, state); + + if (!wait_for_completion_timeout(&ctrl->idle_comp, + IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) + pr_warn("PUSH_VCPF pattern timedout\n"); + + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); +} + static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, struct msm_dp_panel *msm_dp_panel) { @@ -2994,6 +3044,13 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, ret = IRQ_HANDLED; } + isr = msm_dp_ctrl_get_mst_interrupt(ctrl); + if (isr & (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT)) { + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); + complete(&ctrl->idle_comp); + ret = IRQ_HANDLED; + } + /* DP aux isr */ isr = msm_dp_ctrl_get_aux_interrupt(ctrl); if (isr) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index e1d10ae20f705..88a02d52f61c6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -27,6 +27,7 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index dccd3df368593..6b871c0c55e1a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1524,7 +1524,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_ctrl_push_vcpf(msm_dp_display->ctrl, msm_dp_display->panel); msm_dp_ctrl_mst_stream_channel_slot_setup(msm_dp_display->ctrl); msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index ef2ded8ec4ea5..cbbcc0dbf6520 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -39,6 +39,8 @@ u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg) return reg; switch (reg) { + case REG_DP_STATE_CTRL: + return is_s1 ? REG_DP_STATE_CTRL : REG_DP_MSTLINK_STATE_CTRL; case REG_DP_CONFIGURATION_CTRL: return is_s1 ? REG_DP1_CONFIGURATION_CTRL : REG_DP_MSTLINK_CONFIGURATION_CTRL; case REG_DP_SOFTWARE_MVID: diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index f2bd96f3bbd01..ade7b362d650c 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -42,9 +42,13 @@ #define DP_INTR_FRAME_END BIT(6) #define DP_INTR_CRC_UPDATED BIT(9) +#define DP_INTR_DP0_VCPF_SENT BIT(0) +#define DP_INTR_DP1_VCPF_SENT BIT(3) + #define REG_DP_INTR_STATUS3 (0x00000028) #define REG_DP_INTR_STATUS4 (0x0000002C) +#define REG_DP_INTR_STATUS5 (0x00000034) #define PSR_UPDATE_INT (0x00000001) #define PSR_CAPTURE_INT (0x00000004) #define PSR_EXIT_INT (0x00000010) @@ -143,6 +147,8 @@ #define DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN (0x00000040) #define DP_STATE_CTRL_SEND_VIDEO (0x00000080) #define DP_STATE_CTRL_PUSH_IDLE (0x00000100) +#define DP_DP0_PUSH_VCPF BIT(12) +#define DP_DP1_PUSH_VCPF BIT(14) #define REG_DP_CONFIGURATION_CTRL (0x00000008) #define DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK (0x00000001) @@ -368,6 +374,8 @@ #define REG_DP_DP0_RG (0x000004F8) #define REG_DP_DP1_RG (0x000004FC) +#define REG_DP_MSTLINK_STATE_CTRL (0x00000000) +#define DP_MSTLINK_PUSH_VCPF BIT(12) #define REG_DP_MSTLINK_CONFIGURATION_CTRL (0x00000034) #define REG_DP_MSTLINK_TIMESLOT_1_32 (0x00000038) #define REG_DP_MSTLINK_TIMESLOT_33_63 (0x0000003C) From 6f205c988db5c20f30593a8c969429940d9fb30b Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:31 +0800 Subject: [PATCH 0750/1058] FROMLIST: drm/msm/dp: Always program MST_FIFO_CONSTANT_FILL for MST use cases As per the hardware programming guide, MST_FIFO_CONSTANT_FILL must always be programmed when operating in MST mode. Ensure the register is configured accordingly. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-10-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 12 ++++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c4f1a68b1210c..80116e19fbbf4 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -677,6 +677,8 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl msm_dp_ctrl_config_misc1_misc0(ctrl, panel); msm_dp_panel_timing_cfg(panel, ctrl->msm_dp_ctrl.wide_bus_en); + + msm_dp_panel_mst_async_fifo(panel, ctrl->mst_active); } /* diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index cbbcc0dbf6520..ba5ee2ad8924b 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -741,6 +741,18 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) return 0; } +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en) +{ + struct msm_dp_panel_private *panel; + + panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + + if (mst_en) + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x01); + else + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x00); +} + int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, const struct drm_display_mode *adjusted_mode, u32 bpp) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 3e78af9e430dc..edc39ee5268ef 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -73,6 +73,8 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); void msm_dp_panel_enable_vsc_sdp(struct msm_dp_panel *msm_dp_panel, struct dp_sdp *vsc_sdp); void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel); +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en); + /** * is_link_rate_valid() - validates the link rate * @bw_code: link rate requested by the sink From 55be20e07da7857fe5c8ac9e8fa4b8b9cfbf7ce7 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:32 +0800 Subject: [PATCH 0751/1058] FROMLIST: drm/msm/dp: move link-level teardown from display_disable to display_unprepare msm_dp_display_disable() currently mixes stream-level shutdown (disable VSC SDP, off pixel clk, clear power_on) with link-level teardown (PSM config when sink_count==0, off_link, PHY re-init or host PHY exit). For DP MST the same link is shared across multiple streams, so disabling one stream must not tear down the link. Move the link-level steps into msm_dp_display_unprepare() so that display_disable() handles only the per-stream sequence, mirroring the split already present on the prepare path (display_prepare_link vs display_set_mode / display_enable). SST behaviour is unchanged: atomic_post_disable() still calls display_disable() followed by display_unprepare() in the same order, and the cached dp->panel used inside unprepare is the same panel that was previously passed in. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-11-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 6b871c0c55e1a..8680efb766382 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -731,18 +731,6 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id); - /* dongle is still connected but sinks are disconnected */ - if (dp->link->sink_count == 0) - msm_dp_link_psm_config(dp->link, &msm_dp_panel->link_info, true); - - msm_dp_ctrl_off_link(dp->ctrl, dp->panel); - - if (dp->link->sink_count == 0) - /* re-init the PHY so that we can listen to Dongle disconnect */ - msm_dp_ctrl_reinit_phy(dp->ctrl); - else - msm_dp_display_host_phy_exit(dp); - msm_dp_display->power_on = false; drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count); @@ -1533,6 +1521,18 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) { struct msm_dp *msm_dp_display = &dp->msm_dp_display; + /* dongle is still connected but sinks are disconnected */ + if (dp->link->sink_count == 0) + msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); + + msm_dp_ctrl_off_link(dp->ctrl, dp->panel); + + if (dp->link->sink_count == 0) + /* re-init the PHY so that we can listen to Dongle disconnect */ + msm_dp_ctrl_reinit_phy(dp->ctrl); + else + msm_dp_display_host_phy_exit(dp); + pm_runtime_put_sync(&msm_dp_display->pdev->dev); drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); From b014ac64e54615276a34544e1a45f0cfb52dba75 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:33 +0800 Subject: [PATCH 0752/1058] FROMLIST: drm/msm/dp: factor out _helper variants of bridge ops accepting a panel The atomic bridge callbacks (set_mode / enable / disable / post_disable) on dp_display currently hard-code dp->panel. For DP MST every stream has its own msm_dp_panel that the MST encoder owns, so the same enable/disable sequence needs to be invokable against an arbitrary panel. Introduce *_helper variants that take struct msm_dp_panel * and reduce the existing atomic_* callbacks to thin wrappers that pass dp->panel. No SST-path behaviour change. Also drop the static qualifier from msm_dp_display_prepare_link() and msm_dp_display_unprepare() and change them to take struct msm_dp * so the upcoming MST encoder code can drive link-level prepare/unprepare uniformly through the public API. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-12-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 93 +++++++++++++++++++++-------- drivers/gpu/drm/msm/dp/dp_display.h | 12 ++++ 2 files changed, 80 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 8680efb766382..73e4422651973 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -628,12 +628,14 @@ static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, return 0; } -static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) { - struct msm_dp *msm_dp_display = &dp->msm_dp_display; + struct msm_dp_display_private *dp; int rc = 0; bool force_link_train = false; + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); if (msm_dp_display->is_edp) @@ -1457,69 +1459,101 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } -void msm_dp_display_atomic_prepare(struct msm_dp *msm_dp_display, - struct drm_atomic_commit *state) +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel) { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; + + crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_encoder); + if (!crtc) + return 0; + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + return msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, msm_dp_panel); +} + +void msm_dp_display_atomic_prepare(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) +{ int rc = 0; struct msm_dp_display_private *dp; dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - crtc = drm_atomic_get_new_crtc_for_encoder(state, - msm_dp_display->bridge->encoder); - if (!crtc) - return; - crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - - rc = msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, dp->panel); + rc = msm_dp_display_set_mode_helper(msm_dp_display, state, + msm_dp_display->bridge->encoder, dp->panel); if (rc) { DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); return; } - rc = msm_dp_display_prepare_link(dp); + rc = msm_dp_display_prepare_link(msm_dp_display); if (rc) DRM_ERROR("DP display prepare failed, rc=%d\n", rc); } -void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, struct msm_dp_panel *msm_dp_panel) { struct msm_dp_display_private *dp; int rc = 0; dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - msm_dp_display_set_stream_info(msm_dp_display, dp->panel, 0, 0, 0); + msm_dp_display_set_stream_info(msm_dp_display, msm_dp_panel, 0, 0, 0); - rc = msm_dp_display_enable(dp, dp->panel); + rc = msm_dp_display_enable(dp, msm_dp_panel); if (rc) DRM_ERROR("DP display enable failed, rc=%d\n", rc); rc = msm_dp_display_post_enable(msm_dp_display); if (rc) { DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(dp, dp->panel); + msm_dp_display_disable(dp, msm_dp_panel); } drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_set_stream_info(msm_dp_display, dp->panel, 0, 0, 0); + + msm_dp_display_enable_helper(msm_dp_display, dp->panel); +} + +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_ctrl_push_vcpf(dp->ctrl, msm_dp_panel); + msm_dp_ctrl_mst_stream_channel_slot_setup(dp->ctrl); + msm_dp_ctrl_mst_send_act(dp->ctrl, msm_dp_panel); +} + void msm_dp_display_atomic_disable(struct msm_dp *dp) { struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - msm_dp_ctrl_push_vcpf(msm_dp_display->ctrl, msm_dp_display->panel); - msm_dp_ctrl_mst_stream_channel_slot_setup(msm_dp_display->ctrl); - msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); + msm_dp_display_disable_helper(dp, msm_dp_display->panel); } -static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) +void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) { - struct msm_dp *msm_dp_display = &dp->msm_dp_display; + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) @@ -1534,11 +1568,9 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) msm_dp_display_host_phy_exit(dp); pm_runtime_put_sync(&msm_dp_display->pdev->dev); - - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } -void msm_dp_display_atomic_post_disable(struct msm_dp *dp) +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *dp, struct msm_dp_panel *msm_dp_panel) { struct msm_dp_display_private *msm_dp_display; @@ -1549,7 +1581,18 @@ void msm_dp_display_atomic_post_disable(struct msm_dp *dp) msm_dp_display_audio_notify_disable(msm_dp_display); - msm_dp_display_disable(msm_dp_display, msm_dp_display->panel); + msm_dp_display_disable(msm_dp_display, msm_dp_panel); + + drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); +} + +void msm_dp_display_atomic_post_disable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_atomic_post_disable_helper(msm_dp_display, dp->panel); msm_dp_display_unprepare(msm_dp_display); } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 45e2cc2d6adda..55ffa22bb233f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -45,5 +45,17 @@ enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, const struct drm_display_mode *mode); int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, u32 start_slot, u32 num_slots, u32 pbn); +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); +void msm_dp_display_unprepare(struct msm_dp *dp); #endif /* _DP_DISPLAY_H_ */ From e926256bbb5fa0e29081be974c96f8b4f50c1835 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:34 +0800 Subject: [PATCH 0753/1058] FROMLIST: drm/msm/dp: replace power_on with active_stream_cnt for dp_display For DP MST, the link clock and power domain resources stay on until both streams have been disabled OR we receive hotplug. Introduce an active_stream_cnt to track the number of active streams and necessary state handling. Replace the power_on variable with active_stream_cnt as power_on boolean works only for a single stream. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-13-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_audio.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 28 +++++++++++++++++----------- drivers/gpu/drm/msm/dp/dp_display.h | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 41018e82efa10..035e230201fd9 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -284,7 +284,7 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge, * such cases check for connection status and bail out if not * connected. */ - if (!msm_dp_display->power_on) { + if (!msm_dp_display->active_stream_cnt) { rc = -EINVAL; goto end; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 73e4422651973..71e0dbe80201f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -650,7 +650,7 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) if (dp->link->sink_count == 0) return rc; - if (!msm_dp_display->power_on) { + if (!msm_dp_display->active_stream_cnt) { msm_dp_display_host_phy_init(dp); force_link_train = true; } @@ -670,14 +670,10 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, struct msm_dp *msm_dp_display = &dp->msm_dp_display; drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); - if (msm_dp_display->power_on) { - drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); - return 0; - } rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active); - if (!rc) - msm_dp_display->power_on = true; + + msm_dp_display->active_stream_cnt++; return rc; } @@ -726,14 +722,14 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, { struct msm_dp *msm_dp_display = &dp->msm_dp_display; - if (!msm_dp_display->power_on) + if (!msm_dp_display->active_stream_cnt) return 0; msm_dp_panel_disable_vsc_sdp(msm_dp_panel); msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id); - msm_dp_display->power_on = false; + msm_dp_display->active_stream_cnt--; drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count); return 0; @@ -850,10 +846,10 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) * if we are reading registers we need the link clocks to be on * however till DP cable is connected this will not happen as we * do not know the resolution to power up with. Hence check the - * power_on status before dumping DP registers to avoid crash due + * active_stream_cnt status before dumping DP registers to avoid crash due * to unclocked access */ - if (!dp->power_on) + if (!dp->active_stream_cnt) return; msm_disp_snapshot_add_block(disp_state, msm_dp_display->ahb_len, @@ -1535,6 +1531,11 @@ void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + if (!msm_dp_display->active_stream_cnt) { + drm_dbg_dp(dp->drm_dev, "no active streams\n"); + return; + } + msm_dp_ctrl_push_vcpf(dp->ctrl, msm_dp_panel); msm_dp_ctrl_mst_stream_channel_slot_setup(dp->ctrl); msm_dp_ctrl_mst_send_act(dp->ctrl, msm_dp_panel); @@ -1555,6 +1556,11 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + if (msm_dp_display->active_stream_cnt) { + drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); + return; + } + /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 55ffa22bb233f..75dc40261723e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -18,7 +18,7 @@ struct msm_dp { struct drm_bridge *next_bridge; struct drm_bridge *bridge; bool audio_enabled; - bool power_on; + u32 active_stream_cnt; bool mst_active; unsigned int connector_type; bool is_edp; From 9bb18646239835370d613bbeff4d3e3528a34023 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:35 +0800 Subject: [PATCH 0754/1058] FROMLIST: drm/msm/dp: Mark the SST bridge disconnected when mst is active The bridge detect function is only applicable for SST. In MST mode, connector detection is handled by MST bridges. Skips detection for the SST bridge when MST is active. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-14-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 71e0dbe80201f..fc47b29258ad3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -910,6 +910,9 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, priv = container_of(dp, struct msm_dp_display_private, msm_dp_display); + if (dp->mst_active) + return status; + guard(mutex)(&priv->plugged_lock); ret = pm_runtime_resume_and_get(&dp->pdev->dev); if (ret) { @@ -955,6 +958,10 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, status = connector_status_disconnected; } + /* skip for MST */ + if (priv->max_stream > 1 && drm_dp_read_mst_cap(priv->aux, dpcd)) + status = connector_status_disconnected; + end: /* * If we detected the DPRX, leave the controller on so that it doesn't From 1371c8c68b6184ae9f40959ce8db67d3f2293616 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:36 +0800 Subject: [PATCH 0755/1058] FROMLIST: drm/msm/dp: add an API to initialize MST on sink side If the DP controller is capable of supporting multiple streams then initialize the DP sink in MST mode by programming the DP_MSTM_CTRL DPCD register to enable MST mode. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-15-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 48 ++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fc47b29258ad3..4e55024f92209 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "msm_drv.h" @@ -270,6 +271,31 @@ static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd return lttpr_count; } +static void msm_dp_display_mst_init(struct msm_dp_display_private *dp) +{ + u8 old_mstm_ctrl; + struct msm_dp *msm_dp = &dp->msm_dp_display; + int ret; + + /* clear sink MST state */ + drm_dp_dpcd_read_byte(dp->aux, DP_MSTM_CTRL, &old_mstm_ctrl); + + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, 0); + if (ret < 0) { + DRM_ERROR("failed to clear DP_MSTM_CTRL, ret=%d\n", ret); + return; + } + + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, + DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); + if (ret < 0) { + DRM_ERROR("sink MST enablement failed\n"); + return; + } + + msm_dp->mst_active = true; +} + static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) { struct drm_connector *connector = dp->msm_dp_display.connector; @@ -288,14 +314,19 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (rc) goto end; - drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); - drm_edid_connector_update(connector, drm_edid); + if (!(dp->max_stream > 1) || !drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) { + drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); + drm_edid_connector_update(connector, drm_edid); - if (!drm_edid) { - DRM_ERROR("panel edid read failed\n"); - /* check edid read fail is due to unplug */ - if (!msm_dp_aux_is_link_connected(dp->aux)) - return -ETIMEDOUT; + if (!drm_edid) { + DRM_ERROR("panel edid read failed\n"); + /* check edid read fail is due to unplug */ + if (!msm_dp_aux_is_link_connected(dp->aux)) + return -ETIMEDOUT; + } + + if (rc) + goto end; } msm_dp_link_process_request(dp->link); @@ -317,6 +348,9 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) */ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, false); + if (dp->max_stream > 1 && drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) + msm_dp_display_mst_init(dp); + msm_dp_link_reset_phy_params_vx_px(dp->link); end: From ae4f7456daa0c14eead8660456cbdc0373d8f978 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:37 +0800 Subject: [PATCH 0756/1058] FROMLIST: drm/msm/dp: add msm_dp_display_get_panel() to initialize DP panel Add an API msm_dp_display_get_panel() to initialize and return a DP panel to be used by DP MST module. Since some of the fields of DP panel are private, dp_display module needs to initialize these parts and return the panel back. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-16-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 4e55024f92209..528b049dec50b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -565,6 +565,33 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) return rc; } +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id) +{ + struct msm_dp_display_private *dp; + struct msm_dp_panel *dp_panel; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + if (stream_id >= DP_STREAM_MAX || stream_id >= dp->max_stream) { + DRM_ERROR("invalid stream_id %d\n", stream_id); + return NULL; + } + + dp_panel = msm_dp_panel_get(&dp->msm_dp_display.pdev->dev, dp->aux, dp->link, + dp->link_base, dp->mst2link_base, dp->mst3link_base, + dp->pixel_base[stream_id]); + + if (IS_ERR(dp_panel)) { + DRM_ERROR("failed to initialize panel\n"); + return NULL; + } + + dp_panel->stream_id = stream_id; + + return dp_panel; +} + static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 75dc40261723e..676213a48089e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -58,4 +58,6 @@ int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); void msm_dp_display_unprepare(struct msm_dp *dp); +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id); #endif /* _DP_DISPLAY_H_ */ From 37f8eb9f7ae0a42597e8bc56ee9f8dd64e59d965 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:38 +0800 Subject: [PATCH 0757/1058] FROMLIST: drm/msm/dp: add link_ready to manage link-level operations In MST mode, multiple streams share the same DP link. Track a link_ready state so msm_dp_display_prepare_link() runs only once per link and repeated calls are skipped. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-17-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 42 +++++++++++++++++++---------- drivers/gpu/drm/msm/dp/dp_display.h | 1 + 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 528b049dec50b..9fbfd9bb4d120 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -702,6 +702,9 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) if (msm_dp_display->is_edp) msm_dp_hpd_plug_handle(dp); + if (msm_dp_display->link_ready) + return 0; + rc = pm_runtime_resume_and_get(&msm_dp_display->pdev->dev); if (rc) { DRM_ERROR("failed to pm_runtime_resume\n"); @@ -714,14 +717,18 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) if (!msm_dp_display->active_stream_cnt) { msm_dp_display_host_phy_init(dp); force_link_train = true; + + rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); + if (rc) + DRM_ERROR("Failed link training (rc=%d)\n", rc); + // TODO: schedule drm_connector_set_link_status_property() } - rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); - if (rc) - DRM_ERROR("Failed link training (rc=%d)\n", rc); - // TODO: schedule drm_connector_set_link_status_property() + rc = msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); + if (!rc) + msm_dp_display->link_ready = true; - return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); + return rc; } static int msm_dp_display_enable(struct msm_dp_display_private *dp, @@ -1566,16 +1573,16 @@ void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, struct msm_dp_p dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - msm_dp_display_set_stream_info(msm_dp_display, msm_dp_panel, 0, 0, 0); - - rc = msm_dp_display_enable(dp, msm_dp_panel); - if (rc) - DRM_ERROR("DP display enable failed, rc=%d\n", rc); + if (msm_dp_display->link_ready) { + rc = msm_dp_display_enable(dp, msm_dp_panel); + if (rc) + DRM_ERROR("DP display enable failed, rc=%d\n", rc); - rc = msm_dp_display_post_enable(msm_dp_display); - if (rc) { - DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(dp, msm_dp_panel); + rc = msm_dp_display_post_enable(msm_dp_display); + if (rc) { + DRM_ERROR("DP display post enable failed, rc=%d\n", rc); + msm_dp_display_disable(dp, msm_dp_panel); + } } drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); @@ -1624,6 +1631,11 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + if (!msm_dp_display->link_ready) { + drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); + return; + } + if (msm_dp_display->active_stream_cnt) { drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); return; @@ -1642,6 +1654,8 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) msm_dp_display_host_phy_exit(dp); pm_runtime_put_sync(&msm_dp_display->pdev->dev); + + msm_dp_display->link_ready = false; } void msm_dp_display_atomic_post_disable_helper(struct msm_dp *dp, struct msm_dp_panel *msm_dp_panel) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 676213a48089e..0464f8941e8de 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -22,6 +22,7 @@ struct msm_dp { bool mst_active; unsigned int connector_type; bool is_edp; + bool link_ready; struct msm_dp_audio *msm_dp_audio; bool psr_supported; From ad0890a0cbc941ae2621ef39a099fd1ffbe864bf Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:39 +0800 Subject: [PATCH 0758/1058] FROMLIST: drm/msm/dpu: initialize encoders per stream for DP MST Simply initialize MST encoders for MST-capable DP controllers, and introduce msm_dp_get_mst_max_stream to query MST streams. Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-18-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 14 +++++++++++++- drivers/gpu/drm/msm/msm_drv.h | 7 ++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index da3556eb6ecc2..7a00c4094d5c8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -655,7 +655,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, struct msm_display_info info; bool yuv_supported; int rc; - int i; + int i, stream_id, stream_cnt; for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) { if (!priv->kms->dp[i]) @@ -678,6 +678,18 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); return rc; } + + stream_cnt = msm_dp_get_mst_max_stream(priv->kms->dp[i]); + + if (stream_cnt > 1) { + for (stream_id = 0; stream_id < stream_cnt; stream_id++) { + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dp mst display\n"); + return PTR_ERR(encoder); + } + } + } } return 0; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 3787db8770ada..9bb9cdcec32da 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -361,7 +361,7 @@ bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display, bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, const struct drm_display_mode *mode); bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); - +int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); #else static inline int __init msm_dp_register(void) { @@ -378,6 +378,11 @@ static inline int msm_dp_modeset_init(struct msm_dp *dp_display, return -EINVAL; } +static inline int msm_dp_get_mst_max_stream(struct msm_dp *dp_display) +{ + return -EINVAL; +} + static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display) { } From 48d748cc1a95871303215707856b933eac62802a Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:40 +0800 Subject: [PATCH 0759/1058] FROMLIST: drm/msm/dp: initialize dp_mst module for each DP MST controller For each MST capable DP controller, initialize a dp_mst module to manage its DP MST operations. The DP MST module for each controller is the central entity to manage its topology related operations as well as interfacing with the rest of the DP driver. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-19-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 6 +++ drivers/gpu/drm/msm/dp/dp_display.c | 18 ++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_mst_drm.c | 60 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 13 ++++++ drivers/gpu/drm/msm/msm_drv.h | 6 +++ 7 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_mst_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_mst_drm.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index d0c3a4c6703be..31a15636958c8 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -145,7 +145,8 @@ msm-display-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_link.o \ dp/dp_panel.o \ dp/dp_audio.o \ - dp/dp_utils.o + dp/dp_utils.o \ + dp/dp_mst_drm.o msm-display-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 7a00c4094d5c8..91d33b432427f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -682,6 +682,12 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, stream_cnt = msm_dp_get_mst_max_stream(priv->kms->dp[i]); if (stream_cnt > 1) { + rc = msm_dp_mst_register(priv->kms->dp[i]); + if (rc) { + DPU_ERROR("dp_mst_init failed for DP, rc = %d\n", rc); + return rc; + } + for (stream_id = 0; stream_id < stream_cnt; stream_id++) { encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); if (IS_ERR(encoder)) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9fbfd9bb4d120..ce717f9ce5af6 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -28,6 +28,7 @@ #include "dp_drm.h" #include "dp_audio.h" #include "dp_debug.h" +#include "dp_mst_drm.h" static bool psr_enabled = false; module_param(psr_enabled, bool, 0); @@ -351,6 +352,9 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (dp->max_stream > 1 && drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) msm_dp_display_mst_init(dp); + if (dp->msm_dp_display.mst_active) + msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, true); + msm_dp_link_reset_phy_params_vx_px(dp->link); end: @@ -522,6 +526,11 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) dp->panel->dpcd, dp->panel->downstream_ports); + if (dp->msm_dp_display.mst_active) { + msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, false); + dp->msm_dp_display.mst_active = false; + } + /* signal the disconnect event early to ensure proper teardown */ msm_dp_display_handle_plugged_change(&dp->msm_dp_display, false); @@ -1530,6 +1539,15 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } +int msm_dp_mst_register(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + return msm_dp_mst_init(msm_dp_display, dp->max_stream, dp->aux); +} + int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, struct drm_atomic_commit *state, struct drm_encoder *drm_encoder, diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 0464f8941e8de..a185819ec57e8 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -24,6 +24,8 @@ struct msm_dp { bool is_edp; bool link_ready; + void *msm_dp_mst; + struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c new file mode 100644 index 0000000000000..78b8dffe111b9 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include + +#include "dp_mst_drm.h" +#include "dp_panel.h" + +struct msm_dp_mst { + struct drm_dp_mst_topology_mgr mst_mgr; + struct msm_dp *msm_dp; + struct drm_dp_aux *dp_aux; + u32 max_streams; +}; + +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + int rc; + + rc = drm_dp_mst_topology_mgr_set_mst(&mst->mst_mgr, state); + if (rc < 0) { + drm_err(dp_display->drm_dev, + "[MST] failed to set topology mgr state to %d rc:%d\n", state, rc); + } + + drm_dbg_kms(dp_display->drm_dev, "[MST] set_mgr_state state:%d\n", state); + return rc; +} + +int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) +{ + struct drm_device *dev = dp_display->drm_dev; + struct msm_dp_mst *mst; + int ret; + + mst = devm_kzalloc(dev->dev, sizeof(*mst), GFP_KERNEL); + if (!mst) + return -ENOMEM; + + mst->msm_dp = dp_display; + mst->max_streams = max_streams; + mst->dp_aux = drm_aux; + + ret = drm_dp_mst_topology_mgr_init(&mst->mst_mgr, dev, + drm_aux, + 16, + max_streams, + dp_display->connector->base.id); + if (ret) { + drm_err(dev, "[MST] topology manager init failed\n"); + return ret; + } + + dp_display->msm_dp_mst = mst; + return 0; +} diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h new file mode 100644 index 0000000000000..5d411529f6819 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DP_MST_DRM_H_ +#define _DP_MST_DRM_H_ + +#include "dp_display.h" + +int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state); + +#endif /* _DP_MST_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 9bb9cdcec32da..77d65d175d44e 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -362,6 +362,7 @@ bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, const struct drm_display_mode *mode); bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); +int msm_dp_mst_register(struct msm_dp *dp_display); #else static inline int __init msm_dp_register(void) { @@ -383,6 +384,11 @@ static inline int msm_dp_get_mst_max_stream(struct msm_dp *dp_display) return -EINVAL; } +static inline int msm_dp_mst_register(struct msm_dp *dp_display) +{ + return -EINVAL; +} + static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display) { } From ca62082b9f67b1ce5667aba0eb57912de48f6db6 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:41 +0800 Subject: [PATCH 0760/1058] FROMLIST: drm/msm/dpu: expose dpu_encoder ops for DP MST reuse Export dpu_encoder_atomic_mode_set, dpu_encoder_phys_enable and dpu_encoder_phys_disable so MST encoder helper funcs can reuse them. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-20-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 ++++++++++---------- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 6 ++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 778e231d49677..1c74ff6f0dbd4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1149,9 +1149,9 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, } } -static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +void dpu_encoder_atomic_mode_set(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { struct dpu_encoder_virt *dpu_enc; struct msm_drm_private *priv; @@ -1334,8 +1334,8 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc) mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, - struct drm_atomic_commit *state) +void dpu_encoder_phys_enable(struct drm_encoder *drm_enc, + struct drm_atomic_commit *state) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; @@ -1381,8 +1381,8 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, - struct drm_atomic_commit *state) +void dpu_encoder_phys_disable(struct drm_encoder *drm_enc, + struct drm_atomic_commit *state) { struct dpu_encoder_virt *dpu_enc = NULL; struct drm_crtc *crtc; @@ -2739,9 +2739,9 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) } static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { - .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, - .atomic_disable = dpu_encoder_virt_atomic_disable, - .atomic_enable = dpu_encoder_virt_atomic_enable, + .atomic_mode_set = dpu_encoder_atomic_mode_set, + .atomic_disable = dpu_encoder_phys_disable, + .atomic_enable = dpu_encoder_phys_enable, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 4942097e76137..25ade3dbbeda8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -98,4 +98,10 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc); + +void dpu_encoder_phys_enable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void dpu_encoder_phys_disable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void dpu_encoder_atomic_mode_set(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); #endif /* __DPU_ENCODER_H__ */ From 1521ba3de9564d09134b0b90f8c100a6d05ad3d1 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:42 +0800 Subject: [PATCH 0761/1058] FROMLIST: drm/msm/dpu: use msm_dp_get_mst_intf_id() to get the intf id Use msm_dp_get_mst_intf_id() to get the interface ID for the DP MST controller as the intf_id is unique for each MST stream of each DP controller. For DSI/eDP/DP SST, the stream_id is always 0, so existing behavior remains unchanged. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-21-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +++++++++++--------- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1c74ff6f0dbd4..3adfaeaab71da 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1438,18 +1438,21 @@ void dpu_encoder_phys_disable(struct drm_encoder *drm_enc, static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, struct dpu_rm *dpu_rm, - enum dpu_intf_type type, u32 controller_id) + struct msm_display_info *disp_info, u32 controller_id) { - int i = 0; + int i = 0, cnt = 0; + int stream_id = disp_info->stream_id; - if (type == INTF_WB) + if (disp_info->intf_type == INTF_WB) return NULL; + DPU_DEBUG("intf_type 0x%x controller_id %d stream_id %d\n", + disp_info->intf_type, controller_id, stream_id); for (i = 0; i < catalog->intf_count; i++) { - if (catalog->intf[i].type == type - && catalog->intf[i].controller_id == controller_id) { - return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); - } + if (catalog->intf[i].type == disp_info->intf_type && + controller_id == catalog->intf[i].controller_id) + if (cnt++ == stream_id) + return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); } return NULL; @@ -2675,8 +2678,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, i, controller_id, phys_params.split_role); phys_params.hw_intf = dpu_encoder_get_intf(dpu_kms->catalog, &dpu_kms->rm, - disp_info->intf_type, - controller_id); + disp_info, controller_id); if (disp_info->intf_type == INTF_WB && controller_id < WB_MAX) phys_params.hw_wb = dpu_rm_get_wb(&dpu_kms->rm, controller_id); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 25ade3dbbeda8..861d69afbd763 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -28,6 +28,7 @@ * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles * @is_cmd_mode Boolean to indicate if the CMD mode is requested + * @stream_id stream id for which the interface needs to be acquired * @vsync_source: Source of the TE signal for DSI CMD devices */ struct msm_display_info { @@ -35,6 +36,7 @@ struct msm_display_info { uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_cmd_mode; + int stream_id; enum dpu_vsync_source vsync_source; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 91d33b432427f..b32ecd5b07772 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -614,6 +614,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, info.h_tile_instance[info.num_of_h_tiles++] = other; info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->kms->dsi[i]); + info.stream_id = 0; rc = dpu_kms_dsi_set_te_source(&info, priv->kms->dsi[i]); if (rc) { @@ -689,6 +690,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, } for (stream_id = 0; stream_id < stream_cnt; stream_id++) { + info.stream_id = stream_id; encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); if (IS_ERR(encoder)) { DPU_ERROR("encoder init failed for dp mst display\n"); @@ -716,6 +718,7 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, info.num_of_h_tiles = 1; info.h_tile_instance[0] = 0; info.intf_type = INTF_HDMI; + info.stream_id = 0; encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info); if (IS_ERR(encoder)) { @@ -748,6 +751,7 @@ static int _dpu_kms_initialize_writeback(struct drm_device *dev, /* use only WB idx 2 instance for DPU */ info.h_tile_instance[0] = wb_idx; info.intf_type = INTF_WB; + info.stream_id = 0; maxlinewidth = dpu_rm_get_wb(&dpu_kms->rm, info.h_tile_instance[0])->caps->maxlinewidth; From 86c1fa58cb2d1d9ad690b7161eef9fb3f1ddc0e1 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:43 +0800 Subject: [PATCH 0762/1058] FROMLIST: drm/msm/dp: wire MST helpers into atomic check and commit paths Call drm_dp_mst_atomic_check() from msm_atomic_check() so MST-specific state, such as connector and topology changes, is validated as part of the atomic check. Hook the MST helpers into atomic_commit_setup() and atomic_commit_tail() to support non-blocking atomic commits for DisplayPort MST, and ensure MST commits properly wait for dependencies. For SST, non-blocking commits are already handled via commit_tail(), which waits for dependencies in the DRM core. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-22-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/msm_atomic.c | 14 +++++++++++++- drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/msm/msm_kms.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index a8babf1dbe0d3..e70e5088cfe53 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -4,6 +4,7 @@ * Author: Rob Clark */ +#include #include #include @@ -207,7 +208,11 @@ int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state) if (ret) return ret; - return drm_atomic_helper_check(dev, state); + ret = drm_atomic_helper_check(dev, state); + if (ret) + return ret; + + return drm_dp_mst_atomic_check(state); } void msm_atomic_commit_tail(struct drm_atomic_commit *state) @@ -221,6 +226,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_start(async, crtc_mask); + drm_dp_mst_atomic_wait_for_dependencies(state); + kms->funcs->enable_commit(kms); /* @@ -322,3 +329,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_finish(async, crtc_mask); } + +int msm_atomic_commit_setup(struct drm_atomic_commit *state) +{ + return drm_dp_mst_atomic_setup_commit(state); +} diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 77d65d175d44e..23e9945f49f7c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -211,6 +211,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, struct msm_kms *kms, int crtc_idx); void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); void msm_atomic_commit_tail(struct drm_atomic_commit *state); +int msm_atomic_commit_setup(struct drm_atomic_commit *state); int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state); struct drm_atomic_commit *msm_atomic_state_alloc(struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index e5d0ea6294484..33ab30300e16d 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -29,6 +29,7 @@ static const struct drm_mode_config_funcs mode_config_funcs = { static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { .atomic_commit_tail = msm_atomic_commit_tail, + .atomic_commit_setup = msm_atomic_commit_setup, }; static irqreturn_t msm_irq(int irq, void *arg) From bda3e7d60d5bc6b3249214b528eedcc94c88470f Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:14:44 +0800 Subject: [PATCH 0763/1058] FROMLIST: drm/msm/dp: add dp_mst_drm to manage DP MST encoder operations drm/msm/dp: introduce dp_mst_drm for MST stream management Add a dp_mst_drm layer to manage DP MST streams with a clear ownership model between encoder, panel and connector. Each MST stream is represented by a dedicated drm_encoder. At modeset initialization time, one (encoder, dp_panel) pair is created per stream_id and remains fixed for the lifetime of the driver. The dp_panel thus carries a stable stream context, including stream_id and pixel mapping. MST connectors are created and destroyed dynamically on hotplug and are attached to a dp_panel through atomic routing. During an atomic commit, connectors are associated with encoders via atomic_best_encoder(), forming a temporary binding for the duration of the commit. Encoder helper callbacks drive the MST stream lifecycle, including timeslot allocation, link enable/disable and payload programming. A per-MST-instance lock serializes operations on shared link state across multiple streams. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-23-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 6 + drivers/gpu/drm/msm/dp/dp_display.c | 9 + drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_mst_drm.c | 245 ++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 7 + 5 files changed, 269 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index b32ecd5b07772..ac5dc844feada 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -696,6 +696,12 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, DPU_ERROR("encoder init failed for dp mst display\n"); return PTR_ERR(encoder); } + + rc = msm_dp_mst_attach_encoder(priv->kms->dp[i], encoder); + if (rc) { + DPU_ERROR("dp_mst attach_encoder failed, rc = %d\n", rc); + return rc; + } } } } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ce717f9ce5af6..0456d76c2f7f1 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -601,6 +601,15 @@ struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, return dp_panel; } +void msm_dp_display_set_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *dst) +{ + struct msm_dp_display_private *dp = + container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + memcpy(dst, &dp->panel->link_info, sizeof(*dst)); +} + static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index a185819ec57e8..fb6bdd372b52f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -63,4 +63,6 @@ void msm_dp_display_unprepare(struct msm_dp *dp); struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, enum msm_dp_stream_id stream_id); +void msm_dp_display_set_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *dst); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 78b8dffe111b9..6a77fdef85e97 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -4,18 +4,259 @@ */ #include +#include +#include #include #include "dp_mst_drm.h" #include "dp_panel.h" +#include "dpu_encoder.h" + +#define to_dp_mst_connector(x) \ + container_of((x), struct msm_dp_mst_connector, connector) + +struct msm_dp_mst_encoder { + struct drm_encoder *enc; + int stream_id; + struct msm_dp_panel *dp_panel; +}; + +struct msm_dp_mst_connector { + struct drm_connector connector; + struct drm_dp_mst_port *mst_port; + struct msm_dp_mst *dp_mst; +}; + struct msm_dp_mst { struct drm_dp_mst_topology_mgr mst_mgr; + struct msm_dp_mst_encoder mst_encoders[DP_STREAM_MAX]; struct msm_dp *msm_dp; struct drm_dp_aux *dp_aux; u32 max_streams; + struct mutex mst_lock; + struct msm_dp_link_info link_info; }; +static struct msm_dp_panel *msm_dp_mst_panel_from_encoder(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].dp_panel; + } + return NULL; +} + +static void msm_dp_mst_update_timeslots(struct msm_dp_mst *mst, + struct msm_dp_panel *panel, + struct drm_dp_mst_atomic_payload *payload) +{ + if (payload->vc_start_slot < 0) + msm_dp_display_set_stream_info(mst->msm_dp, panel, 1, 0, 0); + else + msm_dp_display_set_stream_info(mst->msm_dp, panel, + payload->vc_start_slot, + payload->time_slots, payload->pbn); + + drm_dbg_kms(mst->msm_dp->drm_dev, + "[MST] stream:%u timeslots vc_start:%d slots:%d pbn:%d\n", + panel->stream_id, payload->vc_start_slot, + payload->time_slots, payload->pbn); +} + +static void msm_dp_mst_stream_enable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = + drm_atomic_get_new_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_port *port = mst_conn->mst_port; + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *payload = + drm_atomic_get_mst_payload_state(mst_state, port); + int rc; + + panel->connector = connector; + + guard(mutex)(&mst->mst_lock); + + rc = msm_dp_display_set_mode_helper(dp_display, state, encoder, panel); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u set_mode failed rc=%d\n", panel->stream_id, rc); + goto out; + } + + rc = msm_dp_display_prepare_link(dp_display); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u prepare_link failed rc=%d\n", panel->stream_id, rc); + msm_dp_display_unprepare(dp_display); + goto out; + } + + drm_dp_mst_update_slots(mst_state, DP_CAP_ANSI_8B10B); + + rc = drm_dp_add_payload_part1(&mst->mst_mgr, mst_state, payload); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] payload allocation failure for conn:%d\n", connector->base.id); + msm_dp_display_unprepare(dp_display); + goto out; + } + + msm_dp_mst_update_timeslots(mst, panel, payload); + + msm_dp_display_enable_helper(dp_display, panel); + + drm_dp_check_act_status(&mst->mst_mgr); + + drm_dp_add_payload_part2(&mst->mst_mgr, payload); + +out: + drm_connector_get(connector); +} + +static void msm_dp_mst_stream_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_topology_state *old_mst_state = + drm_atomic_get_old_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_topology_state *new_mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *old_payload = + drm_atomic_get_mst_payload_state(old_mst_state, mst_conn->mst_port); + struct drm_dp_mst_atomic_payload *new_payload = + drm_atomic_get_mst_payload_state(new_mst_state, mst_conn->mst_port); + + guard(mutex)(&mst->mst_lock); + + drm_dp_remove_payload_part1(&mst->mst_mgr, new_mst_state, new_payload); + + drm_dp_remove_payload_part2(&mst->mst_mgr, new_mst_state, old_payload, new_payload); + + msm_dp_mst_update_timeslots(mst, panel, new_payload); + + msm_dp_display_disable_helper(mst->msm_dp, panel); + + drm_dp_check_act_status(&mst->mst_mgr); +} + +static void msm_dp_mst_stream_post_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + + guard(mutex)(&mst->mst_lock); + + msm_dp_display_atomic_post_disable_helper(mst->msm_dp, panel); + + if (!mst->msm_dp->mst_active) + msm_dp_display_unprepare(mst->msm_dp); + + panel->connector = NULL; + + drm_connector_put(connector); +} + +static int msm_dp_mst_enc_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(conn_state->connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_dp_mst_topology_state *mst_state; + int bpp, pbn, slots; + + if (!conn_state->crtc) + return 0; + + if (!drm_atomic_crtc_needs_modeset(crtc_state) || !crtc_state->active) + return 0; + + bpp = (conn_state->connector->display_info.bpc * 3) ?: 24; /* fallback: assume 8bpc */ + pbn = drm_dp_calc_pbn_mode(crtc_state->mode.clock, bpp << 4); + + mst_state = drm_atomic_get_mst_topology_state(crtc_state->state, &mst->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!dfixed_trunc(mst_state->pbn_div)) { + mst_state->pbn_div = + drm_dp_get_vc_payload_bw(mst->link_info.rate, + mst->link_info.num_lanes); + } + + slots = drm_dp_atomic_find_time_slots(crtc_state->state, &mst->mst_mgr, + mst_conn->mst_port, pbn); + if (slots < 0) + return slots; + + return 0; +} + +static void msm_dp_mst_enc_atomic_enable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + msm_dp_mst_stream_enable(enc, state); + dpu_encoder_phys_enable(enc, state); +} + +static void msm_dp_mst_enc_atomic_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + msm_dp_mst_stream_disable(enc, state); + dpu_encoder_phys_disable(enc, state); + msm_dp_mst_stream_post_disable(enc, state); +} + +static const struct drm_encoder_helper_funcs msm_dp_mst_encoder_helper_funcs = { + .atomic_check = msm_dp_mst_enc_atomic_check, + .atomic_mode_set = dpu_encoder_atomic_mode_set, + .atomic_enable = msm_dp_mst_enc_atomic_enable, + .atomic_disable = msm_dp_mst_enc_atomic_disable, +}; + +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + struct msm_dp_panel *dp_panel; + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (!mst->mst_encoders[i].enc) + break; + } + + dp_panel = msm_dp_display_get_panel(dp_display, i); + if (!dp_panel) { + drm_err(dp_display->drm_dev, + "[MST] failed to allocate panel for stream %d\n", i); + return -ENOMEM; + } + + mst->mst_encoders[i].enc = encoder; + mst->mst_encoders[i].stream_id = i; + mst->mst_encoders[i].dp_panel = dp_panel; + drm_encoder_helper_add(encoder, &msm_dp_mst_encoder_helper_funcs); + + return 0; +} + int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) { struct msm_dp_mst *mst = dp_display->msm_dp_mst; @@ -27,6 +268,9 @@ int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) "[MST] failed to set topology mgr state to %d rc:%d\n", state, rc); } + if (state) + msm_dp_display_set_link_info(dp_display, &mst->link_info); + drm_dbg_kms(dp_display->drm_dev, "[MST] set_mgr_state state:%d\n", state); return rc; } @@ -55,6 +299,7 @@ int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_au return ret; } + mutex_init(&mst->mst_lock); dp_display->msm_dp_mst = mst; return 0; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 23e9945f49f7c..f599ebe670190 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -364,6 +364,8 @@ bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); int msm_dp_mst_register(struct msm_dp *dp_display); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder); + #else static inline int __init msm_dp_register(void) { @@ -390,6 +392,11 @@ static inline int msm_dp_mst_register(struct msm_dp *dp_display) return -EINVAL; } +static inline int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder) +{ + return -EINVAL; +} + static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display) { } From 4d35fe0f03ca3c027e51057aa7de52629cd5bd8c Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:45 +0800 Subject: [PATCH 0764/1058] FROMLIST: drm/msm/dp: add connector abstraction for DP MST Introduce an MST connector abstraction for DP MST, with each MST connector associated with a DP panel and connected through a DRM bridge to an MST encoder. The connector is only used for MST helper callbacks, such as detect, get_modes, and get_encoder. Display enable/disable, hotplug handling, and modeset sequencing continue to be handled by the bridge path. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-24-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_mst_drm.c | 232 ++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 6a77fdef85e97..12b47a413793d 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "dp_mst_drm.h" #include "dp_panel.h" @@ -50,6 +51,18 @@ static struct msm_dp_panel *msm_dp_mst_panel_from_encoder(struct msm_dp_mst *mst return NULL; } +static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].stream_id; + } + return -1; +} + static void msm_dp_mst_update_timeslots(struct msm_dp_mst *mst, struct msm_dp_panel *panel, struct drm_dp_mst_atomic_payload *payload) @@ -275,6 +288,224 @@ int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) return rc; } +/* DP MST Connector OPs */ +static int +msm_dp_mst_connector_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct device *dev = dp_display->drm_dev->dev; + enum drm_connector_status status = connector_status_disconnected; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return status; + + if (dp_display->mst_active) + status = drm_dp_mst_detect_port(connector, + ctx, &mst->mst_mgr, mst_conn->mst_port); + + pm_runtime_put_autosuspend(dev); + + return status; +} + +static int msm_dp_mst_connector_get_modes(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + const struct drm_edid *drm_edid; + int rc; + + drm_edid = drm_dp_mst_edid_read(connector, &mst->mst_mgr, mst_conn->mst_port); + drm_edid_connector_update(connector, drm_edid); + + rc = drm_edid_connector_add_modes(connector); + + drm_edid_free(drm_edid); + + return rc; +} + +static enum drm_mode_status msm_dp_mst_connector_mode_valid(struct drm_connector *connector, + const struct drm_display_mode *mode) +{ + struct msm_dp_mst_connector *mst_conn; + struct drm_dp_mst_port *mst_port; + struct msm_dp *dp_display; + int required_pbn; + + if (drm_connector_is_unregistered(connector)) + return 0; + + mst_conn = to_dp_mst_connector(connector); + mst_port = mst_conn->mst_port; + dp_display = mst_conn->dp_mst->msm_dp; + + /* FIXME: use negotiated bpp (DSC, YUV 4:2:0, etc.); for now use + * 18bpp (6bpc) as a conservative lower bound like i915/nouveau. + */ + required_pbn = drm_dp_calc_pbn_mode(mode->clock, (6 * 3) << 4); + + if (required_pbn > mst_port->full_pbn) { + drm_dbg_dp(dp_display->drm_dev, "mode:%s not supported.\n", mode->name); + return MODE_CLOCK_HIGH; + } + + return msm_dp_display_mode_valid(dp_display, &connector->display_info, mode); +} + +static const struct drm_connector_funcs msm_dp_drm_mst_connector_funcs; + +static struct drm_encoder * +msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_connector_state *conn_state; + struct drm_connector *iter; + struct drm_connector_list_iter conn_iter; + u32 stream_mask = 0; + u32 i; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + if (conn_state->best_encoder) + return conn_state->best_encoder; + + drm_connector_list_iter_begin(connector->dev, &conn_iter); + drm_for_each_connector_iter(iter, &conn_iter) { + struct drm_connector_state *peer_state; + int stream_id; + + if (iter == connector || + iter->funcs != &msm_dp_drm_mst_connector_funcs || + to_dp_mst_connector(iter)->dp_mst != mst) + continue; + + peer_state = drm_atomic_get_new_connector_state(state, iter) ?: iter->state; + if (!peer_state || !peer_state->crtc || !peer_state->best_encoder) + continue; + + stream_id = msm_dp_mst_encoder_stream_id(mst, peer_state->best_encoder); + if (stream_id >= 0 && stream_id < mst->max_streams) + stream_mask |= BIT(stream_id); + } + drm_connector_list_iter_end(&conn_iter); + + for (i = 0; i < mst->max_streams; i++) { + if (!(stream_mask & BIT(i))) { + conn_state->best_encoder = mst->mst_encoders[i].enc; + return mst->mst_encoders[i].enc; + } + } + + return NULL; +} + +static int msm_dp_mst_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + + return drm_dp_atomic_release_time_slots(state, &mst->mst_mgr, mst_conn->mst_port); +} + +static void dp_mst_connector_destroy(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + + drm_connector_cleanup(connector); + drm_dp_mst_put_port_malloc(mst_conn->mst_port); + kfree(mst_conn); +} + +/* DRM MST callbacks */ +static const struct drm_connector_helper_funcs msm_dp_drm_mst_connector_helper_funcs = { + .get_modes = msm_dp_mst_connector_get_modes, + .detect_ctx = msm_dp_mst_connector_detect, + .mode_valid = msm_dp_mst_connector_mode_valid, + .atomic_best_encoder = msm_dp_mst_atomic_best_encoder, + .atomic_check = msm_dp_mst_connector_atomic_check, +}; + +static const struct drm_connector_funcs msm_dp_drm_mst_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .destroy = dp_mst_connector_destroy, + .fill_modes = drm_helper_probe_single_connector_modes, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static struct drm_connector * +msm_dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, const char *pathprop) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + struct drm_device *dev = mst->msm_dp->drm_dev; + struct msm_dp_mst_connector *mst_conn; + struct drm_connector *connector; + int rc, i; + + mst_conn = kzalloc_obj(*mst_conn); + if (!mst_conn) + return NULL; + + connector = &mst_conn->connector; + rc = drm_connector_dynamic_init(dev, connector, + &msm_dp_drm_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort, NULL); + if (rc) + goto err_free; + + mst_conn->dp_mst = mst; + + drm_connector_helper_add(connector, &msm_dp_drm_mst_connector_helper_funcs); + connector->funcs->reset(connector); + + /* add all encoders as possible encoders */ + for (i = 0; i < mst->max_streams; i++) { + rc = drm_connector_attach_encoder(connector, mst->mst_encoders[i].enc); + if (rc) { + drm_err(dev, "[MST] failed to attach encoder:%u to conn:%d rc:%d\n", + mst->mst_encoders[i].enc->base.id, + connector->base.id, rc); + goto err_connector; + } + } + + mst_conn->mst_port = port; + drm_dp_mst_get_port_malloc(port); + + drm_object_attach_property(&connector->base, + dev->mode_config.path_property, 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tile_property, 0); + drm_connector_set_path_property(connector, pathprop); + + drm_dbg_kms(dev, "[MST] add_connector done conn:%d max_streams:%u\n", + connector->base.id, mst->max_streams); + + return connector; + +err_connector: + drm_connector_cleanup(connector); +err_free: + kfree(mst_conn); + return NULL; +} + +static const struct drm_dp_mst_topology_cbs msm_dp_mst_drm_cbs = { + .add_connector = msm_dp_mst_add_connector, +}; + int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) { struct drm_device *dev = dp_display->drm_dev; @@ -285,6 +516,7 @@ int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_au if (!mst) return -ENOMEM; + mst->mst_mgr.cbs = &msm_dp_mst_drm_cbs; mst->msm_dp = dp_display; mst->max_streams = max_streams; mst->dp_aux = drm_aux; From 4f921c2f1c659f7aa6568be9d5db7baa9e38ff46 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 29 Jun 2026 22:14:46 +0800 Subject: [PATCH 0765/1058] FROMLIST: drm/msm/dp: add HPD callback for dp MST Add HPD callback for the MST module which shall be invoked from the dp_display's HPD handler to perform MST specific operations in case of HPD. In MST case, route the HPD messages to MST module. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-mst-v5-25-2ed6aee1867a@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 22 +++++++++++--- drivers/gpu/drm/msm/dp/dp_mst_drm.c | 46 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 1 + 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 0456d76c2f7f1..aa440790dc959 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -455,6 +455,9 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->link->sink_count); + if (dp->plugged && dp->msm_dp_display.mst_active) + return 0; + guard(mutex)(&dp->plugged_lock); ret = pm_runtime_resume_and_get(&pdev->dev); @@ -550,12 +553,18 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) { u32 sink_request; int rc = 0; + struct msm_dp *msm_dp_display = &dp->msm_dp_display; /* irq_hpd can happen at either connected or disconnected state */ drm_dbg_dp(dp->drm_dev, "Before, type=%d, sink_count=%d\n", dp->msm_dp_display.connector_type, dp->link->sink_count); + if (msm_dp_display->mst_active) { + msm_dp_mst_display_hpd_irq(&dp->msm_dp_display); + return 0; + } + /* check for any test request issued by sink */ rc = msm_dp_link_process_request(dp->link); if (!rc) { @@ -1111,9 +1120,13 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) connector_status_connected); /* Send HPD as connected and distinguish it in the notifier */ - if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) - drm_bridge_hpd_notify(dp->msm_dp_display.bridge, - connector_status_connected); + if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { + if (dp->msm_dp_display.mst_active) + msm_dp_irq_hpd_handle(dp); + else + drm_bridge_hpd_notify(dp->msm_dp_display.bridge, + connector_status_connected); + } ret = IRQ_HANDLED; @@ -1776,7 +1789,8 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, msm_dp_hpd_plug_handle(dp); } } else { - msm_dp_hpd_unplug_handle(dp); + if (hpd_link_status == ISR_DISCONNECTED) + msm_dp_hpd_unplug_handle(dp); } pm_runtime_put_sync(&msm_dp_display->pdev->dev); diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 12b47a413793d..56f7a84e77d15 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -36,6 +36,8 @@ struct msm_dp_mst { struct drm_dp_aux *dp_aux; u32 max_streams; struct mutex mst_lock; + /* Serializes HPD IRQ handling between IRQ handler and poll_hpd_irq. */ + struct mutex hpd_irq_lock; struct msm_dp_link_info link_info; }; @@ -288,6 +290,41 @@ int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) return rc; } +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display) +{ + int rc; + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + u8 ack[8] = {}; + u8 esi[4]; + unsigned int esi_res = DP_SINK_COUNT_ESI + 1; + bool handled; + + guard(mutex)(&mst->hpd_irq_lock); + + rc = drm_dp_dpcd_read_data(mst->dp_aux, DP_SINK_COUNT_ESI, esi, 4); + if (rc < 0) { + DRM_ERROR("DPCD sink status read failed, rlen=%d\n", rc); + return; + } + + drm_dbg_dp(dp_display->drm_dev, "MST irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n", + esi[1], esi[2], esi[3]); + + rc = drm_dp_mst_hpd_irq_handle_event(&mst->mst_mgr, esi, ack, &handled); + + /* ack the request */ + if (handled) { + rc = drm_dp_dpcd_write_byte(mst->dp_aux, esi_res, ack[1]); + if (rc < 0) { + DRM_ERROR("DPCD esi_res failed. rc=%d\n", rc); + return; + } + + drm_dp_mst_hpd_irq_send_new_request(&mst->mst_mgr); + } + drm_dbg_dp(dp_display->drm_dev, "MST display hpd_irq handled:%d rc:%d\n", handled, rc); +} + /* DP MST Connector OPs */ static int msm_dp_mst_connector_detect(struct drm_connector *connector, @@ -502,8 +539,16 @@ msm_dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, return NULL; } +static void msm_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + + msm_dp_mst_display_hpd_irq(mst->msm_dp); +} + static const struct drm_dp_mst_topology_cbs msm_dp_mst_drm_cbs = { .add_connector = msm_dp_mst_add_connector, + .poll_hpd_irq = msm_dp_mst_poll_hpd_irq, }; int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) @@ -532,6 +577,7 @@ int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_au } mutex_init(&mst->mst_lock); + mutex_init(&mst->hpd_irq_lock); dp_display->msm_dp_mst = mst; return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h index 5d411529f6819..08e145399cfc7 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -9,5 +9,6 @@ int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state); +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display); #endif /* _DP_MST_DRM_H_ */ From aa806849552635244f82ddf8ed3e79ecb321b19f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:02 +0300 Subject: [PATCH 0766/1058] FROMLIST: drm/connector: report out-of-band IRQ_HPD events The DisplayPort standard defines a special kind of events called IRQ. These events are used to notify DP Source about the events on the Sink side. It is extremely important for DP MST handling, where the MST events are reported through this IRQ. In case of the USB-C DP AltMode there is no actual HPD pulse, but the events are reported through the bits in the AltMode VDOs. Rename drm_connector_oob_hotplug_event() to drm_connector_dp_oob_status() and extend its interface to report IRQ events to the DisplayPort Sink drivers. Acked-by: Heikki Krogerus Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-1-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/drm_connector.c | 20 ++++++++++++-------- drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++-------- include/drm/drm_connector.h | 21 +++++++++++++++++++-- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 11646453aaac9..e7e2fc722b587 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3502,20 +3502,24 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) } /** - * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * drm_connector_dp_oob_status - Report out-of-band hotplug event to DisplayPort connector * @connector_fwnode: fwnode_handle to report the event on * @status: hot plug detect logical state + * @extra_status: additional information provided by the sink without changing + * the HPD state (or in addition to such a change). * - * On some hardware a hotplug event notification may come from outside the display - * driver / device. An example of this is some USB Type-C setups where the hardware - * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD - * status bit to the GPU's DP HPD pin. + * In some cases when DisplayPort signals are being routed through the USB + * Type-C port the hotplug event notifications come from outside of the display + * driver / device. In this case hardware muxes the DisplayPort data and + * AUX-lines but does not pass the altmode HPD status bit to the GPU's DP HPD + * pin. * * This function can be used to report these out-of-band events after obtaining * a drm_connector reference through calling drm_connector_find_by_fwnode(). */ -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status) +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector; @@ -3528,7 +3532,7 @@ void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, drm_connector_put(connector); } -EXPORT_SYMBOL(drm_connector_oob_hotplug_event); +EXPORT_SYMBOL(drm_connector_dp_oob_status); /** diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 263a89c5f3243..ff3659b8f5a2c 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -187,9 +187,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->pending_irq_hpd = true; } } else { - drm_connector_oob_hotplug_event(dp->connector_fwnode, + drm_connector_dp_oob_status(dp->connector_fwnode, hpd ? connector_status_connected : - connector_status_disconnected); + connector_status_disconnected, + (hpd && irq_hpd) ? DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = hpd; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); if (hpd && irq_hpd) { @@ -211,8 +213,11 @@ static int dp_altmode_configured(struct dp_altmode *dp) * configuration is complete to signal HPD. */ if (dp->pending_hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_connected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_connected, + dp->pending_irq_hpd ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); dp->pending_hpd = false; if (dp->pending_irq_hpd) { @@ -396,8 +401,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt, dp->data.status = 0; dp->data.conf = 0; if (dp->hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = false; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); } @@ -828,8 +834,9 @@ void dp_altmode_remove(struct typec_altmode *alt) typec_altmode_put_plug(dp->plug_prime); if (dp->connector_fwnode) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); fwnode_handle_put(dp->connector_fwnode); } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 5f5ca023cd654..577ab35de5e0b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -91,6 +91,22 @@ enum drm_connector_status { connector_status_unknown = 3, }; +/** + * enum drm_connector_status_extra - additional events sent by the sink / + * display together or in replacement of the HPD status changes. + */ +enum drm_connector_status_extra { + /** + * @DRM_CONNECTOR_NO_EXTRA_STATUS: No additional status reported. + */ + DRM_CONNECTOR_NO_EXTRA_STATUS, + /** + * @DRM_CONNECTOR_DP_IRQ_HPD: DisplayPort Sink has sent the + * IRQ_HPD (either by the HPD short pulse or via the AltMode event). + */ + DRM_CONNECTOR_DP_IRQ_HPD, +}; + /** * enum drm_connector_registration_state - userspace registration status for * a &drm_connector @@ -2520,8 +2536,9 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status); +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); From b2b49a732600c3f1cf21478e7d62b15d7160268f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:03 +0300 Subject: [PATCH 0767/1058] FROMLIST: drm/connector: pass down IRQ_HPD to the drivers The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Extend drm_connector_funcs::oob_hotplug_event() to pass the notifications about the IRQ_HPD events down to the individual drivers, letting them handle those as required. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-2-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 17 ++++++++++------- drivers/gpu/drm/drm_connector.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 3 ++- include/drm/drm_connector.h | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 649969fca1413..046efd913064d 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -141,7 +141,8 @@ struct drm_bridge_connector { */ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -154,7 +155,8 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, } static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bridge_connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; @@ -163,7 +165,7 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri connector->status = status; mutex_unlock(&dev->mode_config.mutex); - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, extra_status); drm_kms_helper_connector_hotplug_event(connector); } @@ -171,16 +173,17 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri static void drm_bridge_connector_hpd_cb(void *cb_data, enum drm_connector_status status) { - drm_bridge_connector_handle_hpd(cb_data, status); + drm_bridge_connector_handle_hpd(cb_data, status, DRM_CONNECTOR_NO_EXTRA_STATUS); } static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); - drm_bridge_connector_handle_hpd(bridge_connector, status); + drm_bridge_connector_handle_hpd(bridge_connector, status, extra_status); } static void drm_bridge_connector_enable_hpd(struct drm_connector *connector) @@ -223,7 +226,7 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) if (hdmi) drm_atomic_helper_connector_hdmi_hotplug(connector, status); - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, DRM_CONNECTOR_NO_EXTRA_STATUS); } else { switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DPI: diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index e7e2fc722b587..6bcd47439d5f8 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3528,7 +3528,7 @@ void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, return; if (connector->funcs->oob_hotplug_event) - connector->funcs->oob_hotplug_event(connector, status); + connector->funcs->oob_hotplug_event(connector, status, extra_status); drm_connector_put(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 85d3aa3b9894c..31acb31297233 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6990,7 +6990,8 @@ static int intel_dp_connector_atomic_check(struct drm_connector *_connector, } static void intel_dp_oob_hotplug_event(struct drm_connector *_connector, - enum drm_connector_status hpd_state) + enum drm_connector_status hpd_state, + enum drm_connector_status_extra extra_status) { struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(connector); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 577ab35de5e0b..a4133a28b461a 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1720,7 +1720,8 @@ struct drm_connector_funcs { * has been received from a source outside the display driver / device. */ void (*oob_hotplug_event)(struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @debugfs_init: From 4ca81b55c524024346d6b88b986cc21537e07da9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:04 +0300 Subject: [PATCH 0768/1058] FROMLIST: drm/bridge: aux-hpd: let drivers pass IRQ_HPD events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Let users of aux-hpd, the UCSI and PMIC GLINK drivers pass the IRQ_HPD events to the DisplayPort drivers. The drm_aux_hpd_bridge_notify() is kept to ease merging of the series, preventing extra cross-tree merges. It will be removed once all drivers are converted. The drm_bridge_hpd_notify() function is kept for the drivers which only care about the connector status and will always pass DRM_CONNECTOR_NO_EXTRA_STATUS as the extra status. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-3-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 11 +++++++---- drivers/gpu/drm/drm_bridge.c | 15 +++++++++------ include/drm/bridge/aux-bridge.h | 13 +++++++++++-- include/drm/drm_bridge.h | 22 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index f02a38a2638ad..0e2f0b0461213 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -136,16 +136,19 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_n EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register); /** - * drm_aux_hpd_bridge_notify - notify hot plug detection events + * drm_aux_hpd_bridge_notify_extra - notify hot plug detection events * @dev: device created for the HPD bridge * @status: output connection status + * @extra_status: extra status bits like DRM_CONNECTOR_DP_IRQ_HPD * * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug * detection events for bridges created via drm_dp_hpd_bridge_register(). * * This function shall be called in a context that can sleep. */ -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct auxiliary_device *adev = to_auxiliary_dev(dev); struct drm_aux_hpd_bridge_data *data = auxiliary_get_drvdata(adev); @@ -153,9 +156,9 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta if (!data) return; - drm_bridge_hpd_notify(&data->bridge, status); + drm_bridge_hpd_notify_extra(&data->bridge, status, extra_status); } -EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify); +EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify_extra); static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 687b36eea0c70..84e55db5c1fed 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1495,25 +1495,28 @@ void drm_bridge_hpd_disable(struct drm_bridge *bridge) EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable); /** - * drm_bridge_hpd_notify - notify hot plug detection events + * drm_bridge_hpd_notify_extra - notify hot plug detection and sink IRQ events * @bridge: bridge control structure * @status: output connection status + * @extra_status: additional status recorded by the sink * * Bridge drivers shall call this function to report hot plug events when they - * detect a change in the output status, when hot plug detection has been - * enabled by drm_bridge_hpd_enable(). + * detect a change in the output status or when the sink has reported extra HPD + * status events (like the IRQ_HPD in case of the DisplayPort), when hot plug + * detection has been enabled by drm_bridge_hpd_enable(). * * This function shall be called in a context that can sleep. */ -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status) +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { mutex_lock(&bridge->hpd_mutex); if (bridge->hpd_cb) bridge->hpd_cb(bridge->hpd_data, status); mutex_unlock(&bridge->hpd_mutex); } -EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify); +EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify_extra); #ifdef CONFIG_OF /** diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index c2f5a855512f3..f9a86886b0dfa 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -25,7 +25,9 @@ struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, str int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev); struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_node *np); -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status); +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); #else static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np) @@ -44,9 +46,16 @@ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent, return NULL; } -static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +static inline void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { } #endif +static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +{ + drm_aux_hpd_bridge_notify_extra(dev, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} + #endif diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 4ba3a5deef9a6..78b0d83ef2aa9 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1581,8 +1581,26 @@ void drm_bridge_hpd_enable(struct drm_bridge *bridge, enum drm_connector_status status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status); +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); + +/** + * drm_bridge_hpd_notify - notify hot plug detection events + * @bridge: bridge control structure + * @status: output connection status + * + * Bridge drivers shall call this function to report hot plug events when they + * detect a change in the output status, when hot plug detection has been + * enabled by drm_bridge_hpd_enable(). + * + * This function shall be called in a context that can sleep. + */ +static inline void drm_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status) +{ + drm_bridge_hpd_notify_extra(bridge, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} #ifdef CONFIG_DRM_PANEL_BRIDGE bool drm_bridge_is_panel(const struct drm_bridge *bridge); From ea6d7c4d884c8efa1c3341bfb2414258d06d463f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:05 +0300 Subject: [PATCH 0769/1058] FROMLIST: drm/bridge: pass extra events to the HPD callback The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Bridge drivers report these events through the drm_bridge_hpd_notify_extra(). Pass down the extra status to the HPD callback, specified during the drm_bridge_hpd_enable(), letting underlying drivers (e.g. drm_bridge_connector) to receive these events. Signed-off-by: Dmitry Baryshkov Acked-by: Francesco Dolcini # lt8912b Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-4-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/chrontel-ch7033.c | 3 ++- drivers/gpu/drm/bridge/lontium-lt8912b.c | 3 ++- drivers/gpu/drm/bridge/ti-tfp410.c | 3 ++- drivers/gpu/drm/display/drm_bridge_connector.c | 5 +++-- drivers/gpu/drm/drm_bridge.c | 5 +++-- include/drm/drm_bridge.h | 6 ++++-- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index a237c65ebd690..35df99b02c9c7 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -258,7 +258,8 @@ static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = { .best_encoder = ch7033_connector_best_encoder, }; -static void ch7033_hpd_event(void *arg, enum drm_connector_status status) +static void ch7033_hpd_event(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct ch7033_priv *priv = arg; diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 729b12b674706..b8e643cf1d4da 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -505,7 +505,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) return 0; } -static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status) +static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct lt8912 *lt = data; diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index bf4ab4eaf2697..e2eedaaa3552e 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -110,7 +110,8 @@ static void tfp410_hpd_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dvi->bridge.dev); } -static void tfp410_hpd_callback(void *arg, enum drm_connector_status status) +static void tfp410_hpd_callback(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct tfp410 *dvi = arg; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 046efd913064d..a34643d3ddef8 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -171,9 +171,10 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri } static void drm_bridge_connector_hpd_cb(void *cb_data, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { - drm_bridge_connector_handle_hpd(cb_data, status, DRM_CONNECTOR_NO_EXTRA_STATUS); + drm_bridge_connector_handle_hpd(cb_data, status, extra_status); } static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector, diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 84e55db5c1fed..3fd3e7bac588c 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1445,7 +1445,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_edid_read); */ void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data) { if (!(bridge->ops & DRM_BRIDGE_OP_HPD)) @@ -1513,7 +1514,7 @@ void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, { mutex_lock(&bridge->hpd_mutex); if (bridge->hpd_cb) - bridge->hpd_cb(bridge->hpd_data, status); + bridge->hpd_cb(bridge->hpd_data, status, extra_status); mutex_unlock(&bridge->hpd_mutex); } EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify_extra); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 78b0d83ef2aa9..6a5edfda2ddd4 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1260,7 +1260,8 @@ struct drm_bridge { * @hpd_cb: Hot plug detection callback, registered with * drm_bridge_hpd_enable(). */ - void (*hpd_cb)(void *data, enum drm_connector_status status); + void (*hpd_cb)(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @hpd_data: Private data passed to the Hot plug detection callback * @hpd_cb. @@ -1578,7 +1579,8 @@ const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *connector); void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, From 42c626b077bc64f034bb72c4e1455c16804b506a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:06 +0300 Subject: [PATCH 0770/1058] FROMLIST: drm/bridge: pass down IRQ_HPD to the drivers The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass down the extra status to the bridge drivers via the hpd_notify() callback, letting DP bridges to act accordingly. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-5-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 ++- drivers/gpu/drm/display/drm_bridge_connector.c | 2 +- drivers/gpu/drm/meson/meson_encoder_hdmi.c | 3 ++- drivers/gpu/drm/msm/dp/dp_display.c | 3 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 ++- include/drm/drm_bridge.h | 3 ++- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index b6bf2fe7cb2ce..21f685d30f3cb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -437,7 +437,8 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { const struct drm_edid *drm_edid; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index a34643d3ddef8..8f7075fd2aa5c 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -150,7 +150,7 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, /* Notify all bridges in the pipeline of hotplug events. */ drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) { if (bridge->funcs->hpd_notify) - bridge->funcs->hpd_notify(bridge, connector, status); + bridge->funcs->hpd_notify(bridge, connector, status, extra_status); } } diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 55c0601df3c62..4aecf0ffcf75c 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -323,7 +323,8 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index aa440790dc959..b930331d2173a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1762,7 +1762,8 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge) void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge); struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index da412c788503c..f6b96c27408af 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -31,6 +31,7 @@ void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); #endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e306247ed8a05..d02d432abde46 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -429,7 +429,8 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge, static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 6a5edfda2ddd4..9c4c88024cc50 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -615,7 +615,8 @@ struct drm_bridge_funcs { */ void (*hpd_notify)(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @hpd_enable: From 75e89bf376037244becd840a43c05d56a0b3daa9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:07 +0300 Subject: [PATCH 0771/1058] FROMLIST: drm/msm: dp: handle the IRQ_HPD events reported by USB-C The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side, for example DP MST events. Let the MSM DisplayPort driver properly track and handle IRQ_HPD delivered over the OOB events (e.g. from the USB-C AltMode handler). Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-6-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index b930331d2173a..5b2b0fd36d587 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1781,11 +1781,12 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, msm_dp_display->connector_type, hpd_link_status, status); if (status == connector_status_connected) { - if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { + if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT || + extra_status == DRM_CONNECTOR_DP_IRQ_HPD) { + msm_dp_irq_hpd_handle(dp); + } else if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { msm_dp_hpd_unplug_handle(dp); msm_dp_hpd_plug_handle(dp); - } else if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) { - msm_dp_irq_hpd_handle(dp); } else { msm_dp_hpd_plug_handle(dp); } From 385444bde6f40ad34d4875bfb13fc5e9e80babe9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:08 +0300 Subject: [PATCH 0772/1058] FROMLIST: soc: qcom: pmic-glink-altmode: pass down HPD_IRQ events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass IRQ_HPD events from the firmware to the HPD bridge, letting those to be delivered to the DisplayPort driver. Reviewed-by: Konrad Dybcio Acked-by: Bjorn Andersson Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-7-30b62b335487@oss.qualcomm.com/ --- drivers/soc/qcom/pmic_glink_altmode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 619bad2c27eeb..946eb20b8f836 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -373,7 +373,11 @@ static void pmic_glink_altmode_worker(struct work_struct *work) else conn_status = connector_status_disconnected; - drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status); + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + conn_status, + alt_port->hpd_irq ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) { if (alt_port->svid == USB_TYPEC_TBT_SID) pmic_glink_altmode_enable_tbt(altmode, alt_port); From e8eef33d9315453a5e40e22a02c4aff7d670bb03 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:09 +0300 Subject: [PATCH 0773/1058] FROMLIST: usb: typec: ucsi: huawei-gaokun: pass down HPD_IRQ events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass IRQ_HPD events from the EC to the HPD bridge, letting those to be delivered to the DisplayPort driver. Reviewed-by: Pengyu Luo Acked-by: Heikki Krogerus Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-8-30b62b335487@oss.qualcomm.com/ --- drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c index ad669d2f8b9ce..2e3e00d577d4c 100644 --- a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c +++ b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c @@ -315,10 +315,13 @@ static void gaokun_ucsi_handle_usb_mode(struct gaokun_ucsi_port *port) /* UCSI callback .connector_status() have set orientation */ if (port->bridge && port->svid == USB_TYPEC_DP_SID) - drm_aux_hpd_bridge_notify(&port->bridge->dev, - port->hpd_state ? - connector_status_connected : - connector_status_disconnected); + drm_aux_hpd_bridge_notify_extra(&port->bridge->dev, + port->hpd_state ? + connector_status_connected : + connector_status_disconnected, + port->hpd_irq ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); gaokun_ec_ucsi_pan_ack(uec->ec, port->idx); } From 7e1a4edbb247dfe15e61154b400bfaa9108005ac Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:48:03 +0800 Subject: [PATCH 0774/1058] FROMLIST: drm/bridge: allow hpd_notify() to suppress connector hotplug events The bridge connector framework currently invokes all bridge hpd_notify() callbacks and unconditionally emits a connector hotplug event afterwards. However, not every HPD notification requires a userspace hotplug event. In particular, DP MST bridges may use hpd_notify() to propagate HPD and IRQ notifications through the bridge chain while the actual hotplug handling is performed by the DRM DP MST core. Connector creation, removal and userspace hotplug events are already managed by the MST topology framework. Allow hpd_notify() implementations to suppress the bridge connector hotplug event by introducing a bool *send_hotplug parameter. Drivers can clear this flag when HPD processing should not result in a connector hotplug notification. A NULL pointer indicates that hotplug suppression is not supported by the caller, such as the connector detect polling path. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-msttypec-v1-1-646a10256233@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 ++- drivers/gpu/drm/display/drm_bridge_connector.c | 15 +++++++++------ drivers/gpu/drm/meson/meson_encoder_hdmi.c | 3 ++- drivers/gpu/drm/msm/dp/dp_display.c | 3 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 ++- include/drm/drm_bridge.h | 3 ++- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 21f685d30f3cb..3e8dff3175d36 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -438,7 +438,8 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { const struct drm_edid *drm_edid; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 8f7075fd2aa5c..5edca47a025f5 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -142,7 +142,8 @@ struct drm_bridge_connector { static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -150,13 +151,14 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, /* Notify all bridges in the pipeline of hotplug events. */ drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) { if (bridge->funcs->hpd_notify) - bridge->funcs->hpd_notify(bridge, connector, status, extra_status); + bridge->funcs->hpd_notify(bridge, connector, status, + extra_status, send_hotplug); } } static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bridge_connector, - enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; @@ -165,7 +167,7 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri connector->status = status; mutex_unlock(&dev->mode_config.mutex); - drm_bridge_connector_hpd_notify(connector, status, extra_status); + drm_bridge_connector_hpd_notify(connector, status, extra_status, NULL); drm_kms_helper_connector_hotplug_event(connector); } @@ -227,7 +229,8 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) if (hdmi) drm_atomic_helper_connector_hdmi_hotplug(connector, status); - drm_bridge_connector_hpd_notify(connector, status, DRM_CONNECTOR_NO_EXTRA_STATUS); + drm_bridge_connector_hpd_notify(connector, status, + DRM_CONNECTOR_NO_EXTRA_STATUS, NULL); } else { switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DPI: diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 4aecf0ffcf75c..a67e7b365c5b3 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -324,7 +324,8 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 5b2b0fd36d587..32bb358b07871 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1763,7 +1763,8 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge) void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge); struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index f6b96c27408af..07ddcd0559626 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -32,6 +32,7 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status); + enum drm_connector_status_extra extra_status, + bool *send_hotplug); #endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index d02d432abde46..ad659cef16f58 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -430,7 +430,8 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge, static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status) + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 9c4c88024cc50..e6de665ce8f65 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -616,7 +616,8 @@ struct drm_bridge_funcs { void (*hpd_notify)(struct drm_bridge *bridge, struct drm_connector *connector, enum drm_connector_status status, - enum drm_connector_status_extra extra_status); + enum drm_connector_status_extra extra_status, + bool *send_hotplug); /** * @hpd_enable: From 8fb8c44c25bafc98e8fc1f30b60ecc29eb2e5296 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:48:04 +0800 Subject: [PATCH 0775/1058] FROMLIST: drm/bridge_connector: preserve connector status for IRQ-only HPD events The bridge connector HPD handling path currently updates connector->status for every hpd_notify() invocation. This does not work well for IRQ-only notifications where the event being reported is carried by extra_status and no connector status transition is associated with it. One example is DP MST. HPD IRQs are propagated through drm_bridge_hpd_notify_*() so that bridge drivers can process the notification. During MST operation, however, the SST connector attached to the bridge connector is intentionally kept disconnected while the MST topology manager handles all connector creation, removal and hotplug processing. Updating connector->status for an IRQ-only MST notification may cause the SST connector state to oscillate between connected and disconnected depending on the notification path. These artificial state transitions can later be detected by the polling logic and result in unnecessary hotplug events being generated. Userspace then re-probes connector status, potentially triggering the same sequence again. Treat notifications with status == connector_status_unknown and a valid extra_status as IRQ-only events. Forward the notification to bridge drivers without modifying connector->status. This keeps IRQ delivery working while leaving connector state management to the component that actually owns it, such as the DP MST topology framework. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-msttypec-v1-2-646a10256233@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 5edca47a025f5..7334d66776042 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -163,6 +163,18 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; + /* + * IRQ-only notification: extra_status carries the event but + * status is unknown — do not overwrite connector->status. + */ + if (status == connector_status_unknown && + extra_status != DRM_CONNECTOR_NO_EXTRA_STATUS) { + drm_bridge_connector_hpd_notify(connector, + connector->status, + extra_status, NULL); + return; + } + mutex_lock(&dev->mode_config.mutex); connector->status = status; mutex_unlock(&dev->mode_config.mutex); From 50d5b49240f674e48ce1558e147276ef26095e01 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:48:05 +0800 Subject: [PATCH 0776/1058] FROMLIST: drm/msm/dp: suppress bridge hotplug events during MST operation The DP MST framework already generates the required hotplug events for MST topology changes. Suppress connector hotplug event generation from the bridge connector path while MST is active, and continue propagating HPD notifications to the DP driver. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-msttypec-v1-3-646a10256233@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 6 ++++-- drivers/gpu/drm/msm/dp/dp_display.c | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 7334d66776042..82ed0dc450abc 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -162,6 +162,7 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri { struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; + bool send_hotplug = true; /* * IRQ-only notification: extra_status carries the event but @@ -179,9 +180,10 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri connector->status = status; mutex_unlock(&dev->mode_config.mutex); - drm_bridge_connector_hpd_notify(connector, status, extra_status, NULL); + drm_bridge_connector_hpd_notify(connector, status, extra_status, &send_hotplug); - drm_kms_helper_connector_hotplug_event(connector); + if (send_hotplug) + drm_kms_helper_connector_hotplug_event(connector); } static void drm_bridge_connector_hpd_cb(void *cb_data, diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 32bb358b07871..691dbef0e9abb 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1790,10 +1790,17 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, msm_dp_hpd_plug_handle(dp); } else { msm_dp_hpd_plug_handle(dp); + /* mst_active is set in plug_handle; suppress SST hotplug */ + if (send_hotplug && msm_dp_display->mst_active) + *send_hotplug = false; } } else { - if (hpd_link_status == ISR_DISCONNECTED) + if (!msm_dp_display->mst_active) { msm_dp_hpd_unplug_handle(dp); + } else if (send_hotplug) { + msm_dp_hpd_unplug_handle(dp); + *send_hotplug = false; + } } pm_runtime_put_sync(&msm_dp_display->pdev->dev); From 724f1acaf8842f6645faa6b8b98c9dd80bd755e0 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:48:06 +0800 Subject: [PATCH 0777/1058] FROMLIST: drm/msm/dp: report IRQ_HPD as an IRQ-only notification MST reuses the SST connector bridge to propagate HPD IRQ events through the bridge chain. For IRQ_HPD notifications there is no connector state transition to report. Use connector_status_unknown together with DRM_CONNECTOR_DP_IRQ_HPD so that the bridge connector framework treats them as IRQ-only notifications and forwards them without modifying connector state. The DP driver handles IRQ_HPD events based on DRM_CONNECTOR_DP_IRQ_HPD rather than connector status transitions. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-msttypec-v1-4-646a10256233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 22 +++++++++------------- drivers/soc/qcom/pmic_glink_altmode.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 691dbef0e9abb..d28369d1a5fa9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1119,14 +1119,10 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) drm_bridge_hpd_notify(dp->msm_dp_display.bridge, connector_status_connected); - /* Send HPD as connected and distinguish it in the notifier */ - if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { - if (dp->msm_dp_display.mst_active) - msm_dp_irq_hpd_handle(dp); - else - drm_bridge_hpd_notify(dp->msm_dp_display.bridge, - connector_status_connected); - } + if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) + drm_bridge_hpd_notify_extra(dp->msm_dp_display.bridge, + connector_status_unknown, + DRM_CONNECTOR_DP_IRQ_HPD); ret = IRQ_HANDLED; @@ -1781,11 +1777,11 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, drm_dbg_dp(dp->drm_dev, "type=%d link hpd_link_status=0x%x, status=%d\n", msm_dp_display->connector_type, hpd_link_status, status); - if (status == connector_status_connected) { - if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT || - extra_status == DRM_CONNECTOR_DP_IRQ_HPD) { - msm_dp_irq_hpd_handle(dp); - } else if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { + if (extra_status == DRM_CONNECTOR_DP_IRQ_HPD || + hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) { + msm_dp_irq_hpd_handle(dp); + } else if (status == connector_status_connected) { + if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { msm_dp_hpd_unplug_handle(dp); msm_dp_hpd_plug_handle(dp); } else { diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 946eb20b8f836..28ab8cbb5ef9e 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -373,11 +373,15 @@ static void pmic_glink_altmode_worker(struct work_struct *work) else conn_status = connector_status_disconnected; - drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, - conn_status, - alt_port->hpd_irq ? - DRM_CONNECTOR_DP_IRQ_HPD : - DRM_CONNECTOR_NO_EXTRA_STATUS); + if (alt_port->hpd_irq) { + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + connector_status_unknown, + DRM_CONNECTOR_DP_IRQ_HPD); + } else { + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + conn_status, + DRM_CONNECTOR_NO_EXTRA_STATUS); + } } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) { if (alt_port->svid == USB_TYPEC_TBT_SID) pmic_glink_altmode_enable_tbt(altmode, alt_port); From 4a75aaa34cd89df5c8d59449b76a26d5fc15f906 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 29 Jun 2026 22:48:07 +0800 Subject: [PATCH 0778/1058] FROMLIST: drm/msm/dp: mark the SST connector disconnected when MST is enabled When MST becomes active, the initial HPD plug notification updates the SST connector state to connected. However, the subsequent SST connector detect path reports disconnected while MST is enabled. This connected -> disconnected transition is then observed by the polling logic and may result in an unnecessary hotplug event. Set the SST connector state to disconnected immediately after MST is initialized so that the detect path does not introduce a transient state change. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260629-msm-dp-msttypec-v1-5-646a10256233@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index d28369d1a5fa9..6f21a60f251d7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -352,8 +352,10 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (dp->max_stream > 1 && drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) msm_dp_display_mst_init(dp); - if (dp->msm_dp_display.mst_active) + if (dp->msm_dp_display.mst_active) { + connector->status = connector_status_disconnected; msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, true); + } msm_dp_link_reset_phy_params_vx_px(dp->link); From 3491ee3bc30c5c4041954ee7726128eff5604441 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 23 Oct 2025 12:28:39 +0530 Subject: [PATCH 0779/1058] QCLINUX: firmware: qcom_scm: Add new scm to update Camera QoS Add new SCM call to program secure camera qos settings. For each NIU camera driver can call this scm API which need each NIU's register offsets, value and number of registers offset that need to be programmed. Signed-off-by: Vikram Sharma --- drivers/firmware/qcom/qcom_scm.c | 45 ++++++++++++++++++++++++++ drivers/firmware/qcom/qcom_scm.h | 3 ++ include/linux/firmware/qcom/qcom_scm.h | 10 ++++++ 3 files changed, 58 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 6b601a4b89dbf..760a027bb5f3b 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2563,6 +2563,51 @@ bool qcom_scm_is_available(void) } EXPORT_SYMBOL_GPL(qcom_scm_is_available); +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t cam_qos_cnt, struct qcom_scm_camera_qos *cam_qos) +{ + int ret; + dma_addr_t payload_phys; + u32 *payload_buf = NULL; + u32 payload_size = 0; + + if ((cam_qos_cnt > QCOM_SCM_CAMERA_MAX_QOS_CNT) || (cam_qos_cnt && !cam_qos)) { + pr_err("Invalid input SmartQoS count: %d\n", cam_qos_cnt); + return -EINVAL; + } + + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS, + .owner = ARM_SMCCC_OWNER_SIP, + .args[0] = use_case_id, + .args[2] = payload_size, + .arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL), + }; + + payload_size = cam_qos_cnt * sizeof(struct qcom_scm_camera_qos); + + /* fill all required qos settings */ + if (use_case_id && payload_size && cam_qos) { + payload_buf = dma_alloc_coherent(__scm->dev, + payload_size, &payload_phys, GFP_KERNEL); + if (!payload_buf) + return -ENOMEM; + + memcpy(payload_buf, cam_qos, payload_size); + desc.args[1] = payload_phys; + desc.args[2] = payload_size; + + } + ret = qcom_scm_call(__scm->dev, &desc, NULL); + + if (payload_buf) + dma_free_coherent(__scm->dev, payload_size, payload_buf, payload_phys); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_camera_update_camnoc_qos); + static int qcom_scm_fill_irq_fwspec_params(struct irq_fwspec *fwspec, u32 hwirq) { if (hwirq >= GIC_SPI_BASE && hwirq <= GIC_MAX_SPI) { diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index caab80a73e17f..d8c39bfec47f7 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -175,6 +175,9 @@ int qcom_scm_shm_bridge_enable(struct device *scm_dev); #define QCOM_SCM_INTERRUPTED 1 #define QCOM_SCM_WAITQ_SLEEP 2 +#define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS 0xA + static inline int qcom_scm_remap_error(int err) { switch (err) { diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 5747bd191bf15..d84b5eb6870c6 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -10,10 +10,12 @@ #include #include +#include #define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) #define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0 #define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1 +#define QCOM_SCM_CAMERA_MAX_QOS_CNT 2 #define QCOM_SCM_HDCP_MAX_REQ_CNT 5 struct qcom_scm_hdcp_req { @@ -77,6 +79,14 @@ struct qcom_scm_pas_context { bool use_tzmem; }; +struct qcom_scm_camera_qos { + u32 offset; + u32 val; +}; + +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t qos_cnt, struct qcom_scm_camera_qos *scm_buf); + struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, u32 pas_id, phys_addr_t mem_phys, From eaecc1fbe281c65bcf60ddd2368d8b0f51a32854 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 13 Jan 2026 19:00:16 +0530 Subject: [PATCH 0780/1058] QCLINUX: drivers: increase deferred probe timeout Certain drivers were failing to probe during boot because their dependencies were not ready within the default deferred probe timeout. To address this, increase the deferred probe timeout to allow dependent drivers sufficient time to register and avoid probe failures during system startup. Signed-off-by: Komal Bajaj --- drivers/base/dd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 60c005223844d..25cf17e4b4349 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -257,7 +257,11 @@ static int deferred_devs_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(deferred_devs); -static int driver_deferred_probe_timeout = CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT; +#ifdef CONFIG_MODULES +static int driver_deferred_probe_timeout = 15; +#else +static int driver_deferred_probe_timeout; +#endif static int __init deferred_probe_timeout_setup(char *str) { From 4d677ae8861f2965ce1f44aa7bfb364556b5fd91 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 8 Jan 2026 09:42:56 +0530 Subject: [PATCH 0781/1058] QCLINUX: PCI: Disable L1ss through quirk for Qualcomm SA8775P When PCIe L1ss is enabled, WLAN functionality is completly broken. There are some connectivity issues in this platform mostly with CLKREQ# pin. Disable L1ss as workaround untill actual issue get resolved. Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b09f27f7846fc..a39a62a0e7e04 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2523,6 +2523,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, 0x0451, quirk_disable_aspm_l0s DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PASEMI, 0xa002, quirk_disable_aspm_l0s_l1); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HUAWEI, 0x1105, quirk_disable_aspm_l0s_l1); +static void quirk_disable_aspm_l1ss(struct pci_dev *dev) +{ + pci_disable_link_state(dev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_QCOM, 0x1103, quirk_disable_aspm_l1ss); + /* * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain * Link bit cleared after starting the link retrain process to allow this From b480a075f51d506402f8a081a271e5e05896986e Mon Sep 17 00:00:00 2001 From: Kumar Anurag Date: Tue, 23 Jun 2026 23:54:55 -0700 Subject: [PATCH 0782/1058] FROMLIST: drm/msm/dp: return 0 from audio_prepare when cable is disconnected PipeWire treats a non-zero return from prepare as fatal, marking the DP audio device as a dummy sink when the cable is unplugged. The active_stream_cnt guard already prevents any unclocked hardware access, so return success instead of -EINVAL when the link is not active. Upstream uses variable of power_on while 0.0 kernel uses active_stream_cnt. Hence we use the active_stream_cnt in the current pull request. Link: https://lore.kernel.org/all/20260616151252.3599089-2-kumar.singh@oss.qualcomm.com/ Signed-off-by: Kumar Anurag --- drivers/gpu/drm/msm/dp/dp_audio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 035e230201fd9..8118130a3220f 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -284,10 +284,8 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge, * such cases check for connection status and bail out if not * connected. */ - if (!msm_dp_display->active_stream_cnt) { - rc = -EINVAL; + if (!msm_dp_display->active_stream_cnt) goto end; - } audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { From ea06888f996de3210001c597a856053f219c600e Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 4 Feb 2026 21:40:53 +0530 Subject: [PATCH 0783/1058] WORKAROUND: arm64: dts: qcom: lemans: Disable global IRQ for pcie1 Currently pcie1 global IRQ is blocking a CPU core, due to which ufs is getting blocked and failing. As workaround disable PCIe1 global IRQ for now. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb..4b56d39fe1bfa 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -2897,7 +2897,6 @@ , , , - ; interrupt-names = "msi0", "msi1", "msi2", @@ -2906,7 +2905,6 @@ "msi5", "msi6", "msi7", - "global"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, From bdaf434c0783f0e4ce2a6fad89407c9b94d8287d Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sat, 7 Feb 2026 17:55:39 +0530 Subject: [PATCH 0784/1058] WORKAROUND: scsi: ufs: core: Set uic_cmd_timeout to max It is obsrved that qcs9100-ride fails to boot intermittently due to ufs cmd timeouts. The timeout happens as the ufs threaded-irq fails to schedule within the default UIC_CMD_TIMEOUT_DEFAULT (500 msec) due to console logs spewing at the same moment. Increase timeout to max for now to UIC_CMD_TIMEOUT_MAX (5000 msecs) to allow ufs cmd sequences to complete. Signed-off-by: Shiraz Hashim --- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index d3044a3089b53..f9fbd4cee367a 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -120,7 +120,7 @@ static bool is_mcq_supported(struct ufs_hba *hba) module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); -static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT; +static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_MAX; static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp) { From 87b765abf9f97e489605789adbe9dfed4101cd55 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 4 Mar 2026 12:15:34 +0530 Subject: [PATCH 0785/1058] WORKAROUND: Revert "PCI: dwc: Remove MSI/MSIX capability for Root Port if iMSI-RX is used as MSI controller" commit f5cd8a929c825("PCI: dwc: Remove MSI/MSIX capability for Root Port if iMSI-RX is used as MSI controller") removed MSI & MSIX capability for Root port as dwc controller doesn't support to generate interrupt. Due to this pci framework is falling back to legacy IRQ's. Now controller can generate to interrupts with legacy IRQ's, and actually causing console flood with PCIe continous AER errorsi, these errors will not cause any functional issues. To avoid these errors revert this temporarly untill actual issue got root caused and fixed. Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-designware-host.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 06722259d2e37..6fad88232b47f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1169,17 +1169,6 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp) dw_pcie_dbi_ro_wr_dis(pci); - /* - * The iMSI-RX module does not support receiving MSI or MSI-X generated - * by the Root Port. If iMSI-RX is used as the MSI controller, remove - * the MSI and MSI-X capabilities of the Root Port to allow the drivers - * to fall back to INTx instead. - */ - if (pp->use_imsi_rx && !pp->keep_rp_msi_en) { - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSI); - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSIX); - } - return 0; } EXPORT_SYMBOL_GPL(dw_pcie_setup_rc); From 9a2407e0743ab03d024123c8082ec77a14faec51 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Wed, 4 Mar 2026 00:21:56 -0800 Subject: [PATCH 0786/1058] FROMLIST: phy: qcom: qmp-pcie: Add multiple power-domains support The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs in a bifurcated configuration. Each PHY has its own power domain (phy_gdsc) that must be powered on before initialization per hardware requirements. Current PHY power management assumes a single power domain per PHY, preventing proper setup for this dual-PHY scenario. Add support for multiple power domains by using devm_pm_domain_attach_list() to attach power domains manually, while maintaining compatibility with single power domain PHYs. Enable runtime PM to allow power domain control when the PCIe driver calls phy_power_on/phy_power_off: - Single power domain: QMP PHY platform device directly attaches to power domain and controls it during runtime resume/suspend - Multiple power domains: devm_pm_domain_attach_list() creates virtual devices as power domain suppliers, linked to the QMP PHY platform device as consumer This ensures power domains are properly attached and turned on/off for both single and multiple power domain configurations. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-2-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index d3effad7a074b..110832bdc82d7 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -3440,6 +3441,8 @@ struct qmp_pcie { struct clk_fixed_rate pipe_clk_fixed; struct clk_fixed_rate aux_clk_fixed; + + struct dev_pm_domain_list *pd_list; }; static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val) @@ -5481,6 +5484,16 @@ static int qmp_pcie_probe(struct platform_device *pdev) WARN_ON_ONCE(!qmp->cfg->pwrdn_ctrl); WARN_ON_ONCE(!qmp->cfg->phy_status); + ret = devm_pm_domain_attach_list(dev, NULL, &qmp->pd_list); + if (ret < 0 && ret != -EEXIST) { + dev_err(dev, "Failed to attach power domain\n"); + return ret; + } + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + ret = qmp_pcie_clk_init(qmp); if (ret) return ret; From 02b2204be43daef222f77fa9e9df8b2f7c4eca8c Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Wed, 4 Mar 2026 00:21:57 -0800 Subject: [PATCH 0787/1058] FROMLIST: phy: qcom: qmp-pcie: Support multiple nocsr resets Refactor nocsr reset handling to support multiple nocsr resets required for PHY configurations with bifurcated operation modes. The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs in bifurcation, where each PHY requires its own nocsr reset to be controlled simultaneously. The current implementation only supports a single nocsr reset per PHY configuration. Add num_nocsr and nocsr_list fields to struct qmp_phy_cfg to represent the number and names of a group of nocsr reset names. Initialize these fields for all PHYs that have nocsr resets, allowing the driver to correctly acquire multiple nocsr resets during probe and control them as an array by using reset_control_bulk APIs. The refactoring maintains backward compatibility for existing single nocsr reset configurations while enabling support for multi-PHY scenarios like Glymur's 8-lane bifurcation mode. Additionally, introduces x1e80100_qmp_gen3x2_pciephy_cfg as a separate configuration from sm8550_qmp_gen3x2_pciephy_cfg since the x1e80100 Gen3x2 PHY requires nocsr reset support while the sm8550 Gen3x2 PHY does not. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-3-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 87 +++++++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 110832bdc82d7..168519fdbcac6 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3387,6 +3387,11 @@ struct qmp_phy_cfg { /* resets to be requested */ const char * const *reset_list; int num_resets; + + /* nocsr resets to be requested */ + const char * const *nocsr_reset_list; + int num_nocsr_resets; + /* regulators to be requested */ const char * const *vreg_list; int num_vregs; @@ -3433,7 +3438,7 @@ struct qmp_pcie { int num_pipe_clks; struct reset_control_bulk_data *resets; - struct reset_control *nocsr_reset; + struct reset_control_bulk_data *nocsr_reset; struct regulator_bulk_data *vregs; struct phy *phy; @@ -3500,6 +3505,10 @@ static const char * const sdm845_pciephy_reset_l[] = { "phy", }; +static const char * const sm8550_pciephy_nocsr_reset_l[] = { + "phy_nocsr", +}; + static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = { .serdes = 0, .pcs = 0x1800, @@ -4483,6 +4492,8 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4515,6 +4526,8 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4615,6 +4628,35 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v5, + + .tbls = { + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl), + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v5_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .lanes = 2, @@ -4637,6 +4679,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4670,6 +4714,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4701,6 +4747,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4716,6 +4764,8 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4744,6 +4794,8 @@ static const struct qmp_phy_cfg qmp_v8_gen3x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v8_regs_layout, @@ -4759,6 +4811,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), @@ -4775,6 +4829,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), @@ -4903,7 +4959,7 @@ static int qmp_pcie_init(struct phy *phy) } } - ret = reset_control_assert(qmp->nocsr_reset); + ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset assert failed\n"); goto err_assert_reset; @@ -4940,7 +4996,7 @@ static int qmp_pcie_exit(struct phy *phy) const struct qmp_phy_cfg *cfg = qmp->cfg; if (qmp->nocsr_reset) - reset_control_assert(qmp->nocsr_reset); + reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); else reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -4984,7 +5040,7 @@ static int qmp_pcie_power_on(struct phy *phy) if (ret) return ret; - ret = reset_control_deassert(qmp->nocsr_reset); + ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset deassert failed\n"); goto err_disable_pipe_clk; @@ -5133,14 +5189,25 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp) for (i = 0; i < cfg->num_resets; i++) qmp->resets[i].id = cfg->reset_list[i]; - ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, + qmp->resets); if (ret) return dev_err_probe(dev, ret, "failed to get resets\n"); - qmp->nocsr_reset = devm_reset_control_get_optional_exclusive(dev, "phy_nocsr"); - if (IS_ERR(qmp->nocsr_reset)) - return dev_err_probe(dev, PTR_ERR(qmp->nocsr_reset), - "failed to get no-csr reset\n"); + if (!cfg->num_nocsr_resets) + return 0; + qmp->nocsr_reset = devm_kcalloc(dev, cfg->num_nocsr_resets, + sizeof(*qmp->nocsr_reset), GFP_KERNEL); + if (!qmp->nocsr_reset) + return -ENOMEM; + + for (i = 0; i < cfg->num_nocsr_resets; i++) + qmp->nocsr_reset[i].id = cfg->nocsr_reset_list[i]; + + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets, + qmp->nocsr_reset); + if (ret) + return dev_err_probe(dev, ret, "failed to get no-csr reset\n"); return 0; } @@ -5660,7 +5727,7 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { .data = &sm8750_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy", - .data = &sm8550_qmp_gen3x2_pciephy_cfg, + .data = &x1e80100_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy", .data = &x1e80100_qmp_gen4x2_pciephy_cfg, From 9da80fb7b8d638a224f64aedd85d93ae32c771f0 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Wed, 4 Mar 2026 00:21:58 -0800 Subject: [PATCH 0788/1058] FROMLIST: phy: qcom: qmp-pcie: Add Gen5 8-lanes mode for Glymur The third PCIe controller on Glymur SoC supports 8-lane operation via bifurcation of two PHYs (each requires separate power domian, resets and aux clk). Add dedicated reset/no_csr reset list ("phy_b", "phy_b_nocsr") and clock ("phy_b_aux") required for 8-lane operation. Introduce new glymur_qmp_gen5x8_pciephy_cfg configuration to enable PCIe Gen5 x8 mode. Link: https://lore.kernel.org/all/20260304-glymur_gen5x8_phy-v1-4-849e9a72e125@oss.qualcomm.com/ Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 30 +++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 168519fdbcac6..1d983037470b6 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3484,7 +3484,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) /* list of clocks required by phy */ static const char * const qmp_pciephy_clk_l[] = { - "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", + "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", "phy_b_aux", }; /* list of regulators */ @@ -3509,6 +3509,14 @@ static const char * const sm8550_pciephy_nocsr_reset_l[] = { "phy_nocsr", }; +static const char * const glymur_pciephy_reset_l[] = { + "phy", "phy_b" +}; + +static const char * const glymur_pciephy_nocsr_reset_l[] = { + "phy_nocsr", "phy_b_nocsr", +}; + static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = { .serdes = 0, .pcs = 0x1800, @@ -4840,6 +4848,23 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = { + .lanes = 8, + + .offsets = &qmp_pcie_offsets_v8_50, + + .reset_list = glymur_pciephy_reset_l, + .num_resets = ARRAY_SIZE(glymur_pciephy_reset_l), + .nocsr_reset_list = glymur_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + + .regs = pciephy_v8_50_regs_layout, + + .phy_status = PHYSTATUS_4_20, +}; + static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -5623,6 +5648,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { }, { .compatible = "qcom,glymur-qmp-gen5x4-pcie-phy", .data = &glymur_qmp_gen5x4_pciephy_cfg, + }, { + .compatible = "qcom,glymur-qmp-gen5x8-pcie-phy", + .data = &glymur_qmp_gen5x8_pciephy_cfg, }, { .compatible = "qcom,ipq6018-qmp-pcie-phy", .data = &ipq6018_pciephy_cfg, From 5a941c37817d47c4515a7e3c3be6c7f9acc8120e Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 12 Feb 2026 14:19:12 +0800 Subject: [PATCH 0789/1058] WORKAROUND: phy: qcom: qmp-pcie: Add vdda-refgen and vdda-qref supplies for Glymur The PCIe QMP PHYs on Glymur require stable reference voltage provided by refgen and reference clk provided by qref. The refgen and qref requires power supplies. Add support for vdda-refgen0p9, vdda-refgen1p2 and vdda-qref2 supplies in sm8550_qmp_phy_vreg_l list. Signed-off-by: Qiang Yu --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 1d983037470b6..9c8e9b49456a5 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3493,7 +3493,7 @@ static const char * const qmp_phy_vreg_l[] = { }; static const char * const sm8550_qmp_phy_vreg_l[] = { - "vdda-phy", "vdda-pll", "vdda-qref", + "vdda-phy", "vdda-pll", "vdda-refgen0p9", "vdda-refgen1p2", "vdda-qref","vdda-qref2", }; /* list of resets */ @@ -4821,8 +4821,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v8_50_regs_layout, @@ -4839,8 +4839,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v8_regs_layout, @@ -4857,8 +4857,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = { .num_resets = ARRAY_SIZE(glymur_pciephy_reset_l), .nocsr_reset_list = glymur_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v8_50_regs_layout, From bea6a6f59f4bfd3291bf9e74c2ea9cefc45dc8b7 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Mon, 16 Mar 2026 17:24:55 +0530 Subject: [PATCH 0790/1058] WORKAROUND: remoteproc: qcom: Fix RB8 device hung issue A race condition is occasionally observed on the RB8 platform where the APPS processor removes its turbo vote from the LCX and LMX rails immediately after receiving the handover interrupt from firmware. At that moment, the ADSP firmware vote has not yet been applied to these rails, causing the PMIC shut down and leading the device to hang. Keep the vote of lcx and lmx rails to SVS_L1 from APPS side instead of completely removing it as a WA until actual fix is available. Signed-off-by: Umang Chheda --- drivers/remoteproc/qcom_q6v5_pas.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 808e9609988d3..54cb79fb65916 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -181,6 +181,18 @@ static void qcom_pas_pds_disable(struct qcom_pas *pas, struct device **pds, int i; for (i = 0; i < pd_count; i++) { + /* + * There is a race condition which occurs sometimes for RB8 platform when APPS + * removes it's vote on handover INT from fw - ADSP F/W side vote is not yet + * applied on the lcx and lmx rails because of which PMIC shutdowns shut and device + * goes into hung state. Carry this WA until a proper fix is finalized. + */ + if (of_device_is_compatible(dev_of_node(pas->dev), "qcom,sa8775p-adsp-pas")) { + /* Apply SVS_L1 vote to keep lcx and lmx rails ON */ + dev_pm_genpd_set_performance_state(pds[i], 192); + return; + } + dev_pm_genpd_set_performance_state(pds[i], 0); pm_runtime_put(pds[i]); } From 7306cce68f2a18fcd68e7d6b1b4d373238fc22d6 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Tue, 24 Mar 2026 14:59:48 +0800 Subject: [PATCH 0791/1058] WORKAROUND: arm64: dts: qcom: hamoa-iot-evk: support Bluetooth over both USB and UART On Hamoa boards, a single M.2 slot may host either a UART-based or a USB-based Bluetooth device. As a result, the UART controller node is always present in DT, while the USB path is hot-pluggable. When Bluetooth operates over USB, the presence of the UART DT node still causes the hci_qca UART driver to probe. During probe or power sequencing, the driver may deassert BT_EN, cutting power to the shared Bluetooth device and disconnecting the USB interface. Model BT_EN as an always-on fixed regulator so it cannot be toggled by the UART probe. This prevents the UART driver from interfering with Bluetooth operation when the device is connected over USB. Workaround will be reverted once the M.2 solutionis available upstream. Signed-off-by: Shuai Zhang --- arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 34 ++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index c7ba4b353ddd2..0ab15ea5aa73a 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -522,6 +522,23 @@ regulator-boot-on; }; + vreg_wcn_bt_en: regulator-wcn-bt-en { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_BT_EN"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wcn_bt_en>; + pinctrl-names = "default"; + + regulator-always-on; + regulator-boot-on; + }; + vreg_wwan: regulator-wwan { compatible = "regulator-fixed"; @@ -687,10 +704,9 @@ vddrfa1p2-supply = <&vreg_wcn_1p9>; vddrfa1p8-supply = <&vreg_wcn_1p9>; - bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>; + pinctrl-0 = <&wcn_wlan_en>; pinctrl-names = "default"; regulators { @@ -1519,13 +1535,13 @@ compatible = "qcom,wcn7850-bt"; max-speed = <3200000>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; From f6e888fc67d19c2556f2f5a15edb8410690aa1a9 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Thu, 19 Mar 2026 11:56:41 +0800 Subject: [PATCH 0792/1058] WORKAROUND: power: sequencing: qcom-wcn: skip BT devices without bt-enable GPIO If a Bluetooth consumer device does not have a bt-enable GPIO configured in the power sequencer (for example, when BT_EN is tied high via a hardware pull-up and therefore absent from the DT), the power sequencer should not match the device. In this case, the Bluetooth consumer driver will fall back to its legacy power control path and correctly set power_ctrl_enabled to false. Bluetooth device nodes are conventionally named "bluetooth" in the device tree, so use of_node_name_eq() as a generic check instead of enumerating specific compatible strings. Workaround will be reverted once the M.2 solution is available upstream. Signed-off-by: Shuai Zhang --- drivers/power/sequencing/pwrseq-qcom-wcn.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index b55b4317e21b6..dc83d32415a2d 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -432,6 +432,20 @@ static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, reg_node->parent->parent != ctx->of_node) return PWRSEQ_NO_MATCH; + /* + * If this is a Bluetooth consumer device but the bt-enable GPIO is not + * configured in the power sequencer (e.g. BT_EN is tied high via a + * hardware pull-up and therefore absent from the DT), don't match. + * The consumer driver will fall back to its legacy power control path + * and correctly set power_ctrl_enabled to false. + * + * BT device nodes are conventionally named "bluetooth" in the DT, + * so use of_node_name_eq() as a generic check rather than enumerating + * specific compatible strings. + */ + if (!ctx->bt_gpio && of_node_name_eq(dev_node, "bluetooth")) + return PWRSEQ_NO_MATCH; + return PWRSEQ_MATCH_OK; } From 91e649b6675a4bb6fc7baa4e90c0c4398f4ede43 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 8 May 2026 12:46:38 +0530 Subject: [PATCH 0793/1058] WORKAROUND: Revert "drm/msm/dpu: enable virtual planes by default" Bootup crash seen on kaanapali-mtp board. [ 8.114249][ C0] [drm:dpu_encoder_frame_done_timeout:2731] [dpu error]enc33 frame done timeout [ 8.116480][ T284] Unable to handle kernel paging request at virtual address ffff800080e5e000 [ 8.116488][ T284] Mem abort info: [ 8.116492][ T284] ESR = 0x0000000096000007 [ 8.116497][ T284] EC = 0x25: DABT (current EL), IL = 32 bits [ 8.116502][ T284] SET = 0, FnV = 0 [ 8.116507][ T284] EA = 0, S1PTW = 0 [ 8.116511][ T284] FSC = 0x07: level 3 translation fault [ 8.116516][ T284] Data abort info: [ 8.116519][ T284] ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000 [ 8.116524][ T284] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 [ 8.116529][ T284] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 8.116535][ T284] swapper pgtable: 4k pages, 48-bit VAs, pgdp=00000009bf36c000 [ 8.116541][ T284] [ffff800080e5e000] pgd=0000000000000000, p4d=1000000880346403, pud=1000000880347403, pmd=1000000881e2d403, pte=0000000000000000 [ 8.116567][ T284] Internal error: Oops: 0000000096000007 [#1] SMP Revert the change for now to unblock. This reverts commit b0907ee59e24d3dad572b4ccc6db018b00ca14c8. Signed-off-by: Salendarsingh Gaud --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index da3556eb6ecc2..dbc43e0dc18e3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -52,7 +52,7 @@ #define DPU_DEBUGFS_DIR "msm_dpu" #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask" -bool dpu_use_virtual_planes = true; +bool dpu_use_virtual_planes; module_param(dpu_use_virtual_planes, bool, 0); static int dpu_kms_hw_init(struct msm_kms *kms); From e6ae7a88b1f589b9f34b7359aa586b7ec779a7e0 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Thu, 7 May 2026 12:53:20 +0530 Subject: [PATCH 0794/1058] WORKAROUND: arm64: dts: qcom: purwa-iot-evk: support Bluetooth over both USB and UART On Purwa boards, a single M.2 slot may host either a UART-based or a USB-based Bluetooth device. As a result, the UART controller node is always present in DT, while the USB path is hot-pluggable. When Bluetooth operates over USB, the presence of the UART DT node still causes the hci_qca UART driver to probe. During probe or power sequencing, the driver may deassert BT_EN, cutting power to the shared Bluetooth device and disconnecting the USB interface. Model BT_EN as an always-on fixed regulator so it cannot be toggled by the UART probe. This prevents the UART driver from interfering with Bluetooth operation when the device is connected over USB. Workaround will be reverted once the M.2 solutionis available upstream. Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 34 ++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index ad503beec1d3d..c39081b064b10 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -514,6 +514,23 @@ regulator-boot-on; }; + vreg_wcn_bt_en: regulator-wcn-bt-en { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_BT_EN"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wcn_bt_en>; + pinctrl-names = "default"; + + regulator-always-on; + regulator-boot-on; + }; + vreg_wwan: regulator-wwan { compatible = "regulator-fixed"; @@ -628,10 +645,9 @@ vddrfa1p2-supply = <&vreg_wcn_1p9>; vddrfa1p8-supply = <&vreg_wcn_1p9>; - bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>; + pinctrl-0 = <&wcn_wlan_en>; pinctrl-names = "default"; regulators { @@ -1504,13 +1520,13 @@ compatible = "qcom,wcn7850-bt"; max-speed = <3200000>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; From ab13fae207083b7a641585e36f04716ff65611f8 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Fri, 15 May 2026 00:00:00 +0800 Subject: [PATCH 0795/1058] WORKAROUND: phy: qcom: qmp-pcie: Add vdda-refgen and vdda-qref supplies for Monaco The PCIe QMP PHYs on Monaco (QCS8300) require stable reference voltage provided by refgen and reference clock provided by qref. The refgen and qref require power supplies. Add a new sa8775p_qmp_phy_vreg_l list with vdda-qref and vdda-refgen supplies, and use it for qcs8300_qmp_gen4x2, sa8775p_qmp_gen4x2 and sa8775p_qmp_gen4x4 PCIe PHY configurations. Workaround will be reverted once the vote qref regulator for PCIe available in upstream. Signed-off-by: Ziyue Zhang --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 9c8e9b49456a5..726bbd4a57323 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -3496,6 +3496,10 @@ static const char * const sm8550_qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", "vdda-refgen0p9", "vdda-refgen1p2", "vdda-qref","vdda-qref2", }; +static const char * const sa8775p_qmp_phy_vreg_l[] = { + "vdda-phy", "vdda-pll", "vdda-qref", "vdda-refgen", +}; + /* list of resets */ static const char * const ipq8074_pciephy_reset_l[] = { "phy", "common", @@ -3873,8 +3877,8 @@ static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4587,8 +4591,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4628,8 +4632,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, From adb0982914721a58d2d238d3e68b803986df4781 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Fri, 15 May 2026 00:00:00 +0800 Subject: [PATCH 0796/1058] WORKAROUND: arm64: dts: qcom: qcs8300-ride: Add vdda-qref and vdda-refgen supplies for PCIe PHYs The PCIe QMP PHYs on QCS8300 require stable reference voltage provided by refgen and reference clock provided by qref. Add vdda-qref-supply and vdda-refgen-supply to pcie0_phy and pcie1_phy nodes on the qcs8300-ride board. Workaround will be reverted once the vote qref regulator for PCIe available in upstream. Signed-off-by: Ziyue Zhang --- arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index e9a8553a8d821..25be329a98829 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -638,6 +638,8 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l7a>; + vdda-refgen-supply = <&refgen>; status = "okay"; }; @@ -657,6 +659,8 @@ &pcie1_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l7a>; + vdda-refgen-supply = <&refgen>; status = "okay"; }; From 9224237ccdb47872f0871ed792f2ba1b7abb6188 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 14 May 2026 17:37:04 +0800 Subject: [PATCH 0797/1058] WORKAROUND: arm64: dts: qcom: Add qref supply for PCIe PHYs All PCIe PHYs on X1E80100 require vdda-qref power supplies, but this is missing in the current PHY device tree node. The PCIe port can still function because the regulator L3J, which vdda-qref consumes, is voted by other components. Since the device tree should accurately describe the hardware, add the vdda-qref power supply explicitly in all PCIe PHY device nodes. Workaround will be reverted once the vote qref regulator for PCIe available in upstream. Signed-off-by: Qiang Yu Signed-off-by: Ziyue Zhang --- arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi index 9c5e77df00547..6393a4721b171 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi @@ -400,6 +400,7 @@ &pcie3_phy { vdda-phy-supply = <&vreg_l3c_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -414,6 +415,7 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -428,6 +430,7 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -442,6 +445,7 @@ &pcie6a_phy { vdda-phy-supply = <&vreg_l1d_0p8>; vdda-pll-supply = <&vreg_l2j_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; From c654f35611edfe6616e44761f06c29eae20cb855 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 14 May 2026 17:39:01 +0800 Subject: [PATCH 0798/1058] WORKAROUND: phy: qcom: qmp-pcie: add x1e80100 qref supplies All PCIe PHYs on the X1E80100 SOC require the vdda-qref, which feeds QREF clocks provided by the TCSR device. Hence, restore the vdda-qref request for the 6th and the 3th PCIe instance by reverting commit 031b46b4729b ("phy: qcom: qmp-pcie: drop bogus x1e80100 qref supplies") and commit eb7a22f830f6("phy: qcom: qmp-pcie: drop bogus x1e80100 qref supply"). For the 4th PCIe instance (Gen3 x2), add a new driver data entry, namely x1e80100_qmp_gen3x2_pciephy_cfg, which is a copy of sm8550_qmp_gen3x2_pciephy_cfg but uses sm8550_qmp_phy_vreg_l instead. Workaround will be reverted once the vote qref regulator for PCIe available in upstream. Fixes: eb7a22f830f6 ("phy: qcom: qmp-pcie: drop bogus x1e80100 qref supplies") Fixes: 031b46b4729b ("phy: qcom: qmp-pcie: drop bogus x1e80100 qref supplies") Fixes: 606060ce8fd0 ("phy: qcom-qmp-pcie: Add support for X1E80100 g3x2 and g4x2 PCIE") Cc: Johan Hovold Cc: Abel Vesa Signed-off-by: Wenbin Yao Signed-off-by: Qiang Yu Signed-off-by: Ziyue Zhang --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 726bbd4a57323..b464f0ab037a4 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -4661,8 +4661,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4693,8 +4693,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4728,8 +4728,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4761,8 +4761,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = { .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, From 053e6d92173f16782d8c9765077eb27621198f80 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Thu, 28 May 2026 20:23:39 +0800 Subject: [PATCH 0799/1058] WORKAROUND: power: sequencing: qcom-wcn: skip BT devices without bt-enable GPIO Add a bt_gpio_required flag to the per-platform data to indicate that a chip's BT enable path requires a dedicated GPIO. Only skip matching the "bluetooth" device node when this flag is set and bt_gpio is absent. Previously the bt_gpio check was applied unconditionally, which caused chips like WCN3990 that have no separate BT/WLAN enable pins by design to fail matching even when bt-enable GPIO is legitimately absent from the DT. Set bt_gpio_required for WCN6855 and WCN7850 which do require a dedicated BT enable GPIO. Signed-off-by: Shuai Zhang --- drivers/power/sequencing/pwrseq-qcom-wcn.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index dc83d32415a2d..a68e6fb344fd6 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -25,6 +25,7 @@ struct pwrseq_qcom_wcn_pdata { unsigned int gpio_enable_delay_ms; const struct pwrseq_target_data **targets; bool has_vddio; /* separate VDD IO regulator */ + bool bt_gpio_required; /* BT enable path requires a dedicated GPIO */ int (*match)(struct pwrseq_device *pwrseq, struct device *dev); }; @@ -383,6 +384,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn6855_of_data = { .pwup_delay_ms = 50, .gpio_enable_delay_ms = 5, .targets = pwrseq_qcom_wcn6855_targets, + .bt_gpio_required = true, }; static const char *const pwrseq_wcn7850_vregs[] = { @@ -400,6 +402,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = { .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs), .pwup_delay_ms = 50, .targets = pwrseq_qcom_wcn_targets, + .bt_gpio_required = true, }; static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, @@ -439,11 +442,17 @@ static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, * The consumer driver will fall back to its legacy power control path * and correctly set power_ctrl_enabled to false. * + * Only apply this check for chips whose BT enable path requires a + * dedicated GPIO (bt_gpio_required). Chips like WCN3990 have no + * separate BT/WLAN enable pins by design and must always be matched + * even when bt_gpio is NULL. + * * BT device nodes are conventionally named "bluetooth" in the DT, * so use of_node_name_eq() as a generic check rather than enumerating * specific compatible strings. */ - if (!ctx->bt_gpio && of_node_name_eq(dev_node, "bluetooth")) + if (ctx->pdata->bt_gpio_required && !ctx->bt_gpio && + of_node_name_eq(dev_node, "bluetooth")) return PWRSEQ_NO_MATCH; return PWRSEQ_MATCH_OK; From 966b84f80b6c034974805516294d660d92ad7480 Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Mon, 8 Jun 2026 12:20:46 +0530 Subject: [PATCH 0800/1058] FROMLIST: dt-bindings: net: bluetooth: qcom: document QCC2072 Add the new compatible string for the QCC2072 BT SoC to the Qualcomm Bluetooth DT binding schema. Link: https://lore.kernel.org/all/20260529175342.3363935-1-yepuri.siddu@oss.qualcomm.com/ Signed-off-by: Yepuri Siddu --- .../net/bluetooth/qcom,qcc2072-bt.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml new file mode 100644 index 0000000000000..8e2f15a75d620 --- /dev/null +++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/bluetooth/qcom,qcc2072-bt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCC2072 Bluetooth + +maintainers: + - Balakrishna Godavarthi + - Rocky Liao + +description: + Qualcomm QCC2072 is a UART-based Bluetooth controller. + +properties: + compatible: + enum: + - qcom,qcc2072-bt + +required: + - compatible + +allOf: + - $ref: bluetooth-controller.yaml# + - $ref: qcom,bluetooth-common.yaml# + - $ref: /schemas/serial/serial-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + serial { + bluetooth { + compatible = "qcom,qcc2072-bt"; + max-speed = <3200000>; + }; + }; From cf2e99141ca35a924764b8f5998e554ecae2596a Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Mon, 8 Jun 2026 12:33:14 +0530 Subject: [PATCH 0801/1058] FROMLIST: Bluetooth: qca: add QCC2072 support QCC2072 is a BT/WiFi combo SoC that uses different firmware filenames and requires no external voltage regulators, so add it as a new SoC type. The chip supports the wideband speech and valid LE states capabilities. Its firmware is named using the "orn" prefix and follows the standard rom-version-based scheme: - qca/ornbtfw.tlv - qca/ornnv.bin These firmware files are already present in the linux-firmware repository. Link: https://lore.kernel.org/all/20260529175822.3366535-1-yepuri.siddu@oss.qualcomm.com/ Signed-off-by: Yepuri Siddu --- drivers/bluetooth/btqca.c | 9 +++++++++ drivers/bluetooth/btqca.h | 1 + drivers/bluetooth/hci_qca.c | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 04ebe290bc784..8b2ad10ec2d92 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -845,6 +845,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/hmtbtfw%02x.tlv", rom_ver); break; + case QCA_QCC2072: + snprintf(config.fwname, sizeof(config.fwname), + "qca/ornbtfw%02x.tlv", rom_ver); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", soc_ver); @@ -939,6 +943,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname), "hmtnv", soc_type, ver, rom_ver, boardid); break; + case QCA_QCC2072: + snprintf(config.fwname, sizeof(config.fwname), + "qca/ornnv%02x.bin", rom_ver); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", soc_ver); @@ -1001,6 +1009,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: /* get fw build info */ err = qca_read_fw_build_info(hdev); if (err < 0) diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 8f3c1b1c77b3d..a175ac31e7b23 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -158,6 +158,7 @@ enum qca_btsoc_type { QCA_WCN6750, QCA_WCN6855, QCA_WCN7850, + QCA_QCC2072, }; #if IS_ENABLED(CONFIG_BT_QCA) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 2444471956197..3f9e3d966747d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1372,6 +1372,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) /* Give the controller time to process the request */ switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1459,6 +1460,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1510,6 +1512,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, true); break; @@ -1545,6 +1548,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, false); break; @@ -1861,6 +1865,7 @@ static int qca_power_on(struct hci_dev *hdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: ret = qca_regulator_init(hu); break; @@ -1960,6 +1965,10 @@ static int qca_setup(struct hci_uart *hu) soc_name = "wcn7850"; break; + case QCA_QCC2072: + soc_name = "qcc2072"; + break; + default: soc_name = "ROME/QCA6390"; } @@ -1983,6 +1992,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: if (qcadev && qcadev->bdaddr_property_broken) hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN); @@ -2016,6 +2026,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: break; default: @@ -2169,6 +2180,12 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = { .num_vregs = 4, }; +static const struct qca_device_data qca_soc_data_qcc2072 __maybe_unused = { + .soc_type = QCA_QCC2072, + .num_vregs = 0, + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, +}; + static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = { .soc_type = QCA_WCN6750, .vregs = (struct qca_vreg []) { @@ -2271,6 +2288,7 @@ static void qca_power_off(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: + case QCA_QCC2072: gpiod_set_value_cansleep(qcadev->bt_en, 0); msleep(100); qca_regulator_disable(qcadev); @@ -2417,6 +2435,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->btsoc_type = QCA_ROME; switch (qcadev->btsoc_type) { + case QCA_QCC2072: case QCA_QCA6390: case QCA_WCN3950: case QCA_WCN3988: @@ -2445,6 +2464,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the @@ -2487,6 +2507,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->bt_en && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) power_ctrl_enabled = false; @@ -2495,6 +2516,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (IS_ERR(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) { dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); return PTR_ERR(qcadev->sw_ctrl); @@ -2573,6 +2595,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) struct qca_power *power = qcadev->bt_power; switch (qcadev->btsoc_type) { + case QCA_QCC2072: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2782,6 +2805,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750}, { .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855}, { .compatible = "qcom,wcn7850-bt", .data = &qca_soc_data_wcn7850}, + { .compatible = "qcom,qcc2072-bt", .data = &qca_soc_data_qcc2072}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); From 27d430f65fdc51e5a761d3d7c351e95fb7b166b6 Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Mon, 8 Jun 2026 12:39:25 +0530 Subject: [PATCH 0802/1058] FROMLIST: arm64: dts: qcom: Add M.2 QCC2072 support on qcs6490-rb3gen2 industrial mezzanine Add DTS support for M.2 QCC2072 on Qualcomm qcs6490-rb3gen2 industrial mezzanine board. Link: https://lore.kernel.org/all/20260529180234.3373056-1-yepuri.siddu@oss.qualcomm.com/ Signed-off-by: Yepuri Siddu --- arch/arm64/boot/dts/qcom/Makefile | 2 + ...3gen2-industrial-mezzanine-m2-cologne.dtso | 110 ++++++++++++++++++ .../qcs6490-rb3gen2-industrial-mezzanine.dtso | 4 + 3 files changed, 116 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..28eccecea5dfe 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -179,11 +179,13 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo +qcs6490-rb3gen2-industrial-mezzanine-m2-cologne-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb qcs8300-ride-el2-dtbs := qcs8300-ride.dtb monaco-el2.dtbo diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso new file mode 100644 index 0000000000000..905a40f4b938f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +/dts-v1/; +/plugin/; +#include + +&tlmm { + qup_uart4_sleep_cts: qup-uart4-sleep-cts-state { + pins = "gpio16"; + function = "gpio"; + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; + }; + + qup_uart4_sleep_rts: qup-uart4-sleep-rts-state { + pins = "gpio17"; + function = "gpio"; + /* + * Configure pull-down on RTS. As RTS is active low + * signal, pull it low to indicate the BT SoC that it + * can wakeup the system anytime from suspend state by + * pulling RX low (by sending wakeup bytes). + */ + bias-pull-down; + }; + + qup_uart4_sleep_rx: qup-uart4-sleep-rx-state { + pins = "gpio19"; + function = "gpio"; + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module + * is floating which may cause spurious wakeups. + */ + bias-pull-up; + }; + + qup_uart4_sleep_tx: qup-uart4-sleep-tx-state { + pins = "gpio18"; + function = "gpio"; + /* + * Configure pull-up on TX when it isn't actively driven + * to prevent BT SoC from receiving garbage during sleep. + */ + bias-pull-up; + }; + + sw_ctrl: sw-ctrl-state { + pins = "gpio86"; + function = "gpio"; + bias-pull-down; + }; +}; + +&qup_uart4_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart4_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart4_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart4_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&uart4 { + status = "okay"; + /delete-property/ interrupts; + interrupts-extended = <&intc GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 19 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default", "sleep"; + pinctrl-1 = <&qup_uart4_sleep_cts>, <&qup_uart4_sleep_rts>, + <&qup_uart4_sleep_tx>, <&qup_uart4_sleep_rx>; + + bluetooth: bluetooth { + compatible = "qcom,qcc2072-bt"; + max-speed = <3200000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index 83908db335afa..c96c7f52ea7a0 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -288,3 +288,7 @@ &wifi { status = "disabled"; }; + +&uart7 { + status = "disabled"; +}; From bb534fa9023aabe36eeb33a57d1e00f3dec39313 Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Mon, 8 Jun 2026 12:41:26 +0530 Subject: [PATCH 0803/1058] FROMLIST: Bluetooth: qca: combine NVM and calibration data for QCC2072 QCC2072 requires the NVM and calibration data to be delivered to the controller bundled together in an outer TLV of type 4. After loading the NVM file, load the calibration file (qca/ornbcscal.bin) and combine both into a single buffer with the outer TLV header before passing it to qca_tlv_check_data(). The outer TLV header encodes the combined payload length in the high 24 bits and type 4 in the low 8 bits of the type_len field. If the calibration file is unavailable, fall back to downloading the NVM alone. Link: https://lore.kernel.org/all/20260529180431.3373856-1-yepuri.siddu@oss.qualcomm.com/ Signed-off-by: Yepuri Siddu --- drivers/bluetooth/btqca.c | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 8b2ad10ec2d92..ae3f6e7d8ea95 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -614,6 +614,53 @@ static int qca_download_firmware(struct hci_dev *hdev, memcpy(data, fw->data, size); release_firmware(fw); + /* For QCC2072, combine the NVM (type 2) with the calibration file + * into a single TLV of outer type 4. + */ + if (soc_type == QCA_QCC2072 && config->type == TLV_TYPE_NVM) { + const struct firmware *calib_fw = NULL; + char calib_name[32]; + u8 *combined_data = NULL; + size_t inner_len, combined_size; + struct tlv_type_hdr *outer_hdr; + int err; + + snprintf(calib_name, sizeof(calib_name), + "qca/ornbcscal%02x.bin", rom_ver); + err = request_firmware(&calib_fw, calib_name, &hdev->dev); + if (err) { + bt_dev_err(hdev, "QCA Failed to request file: %s (%d)", + calib_name, err); + goto skip_combination; + } + + bt_dev_info(hdev, "QCA Downloading %s", calib_name); + + inner_len = size + calib_fw->size; + combined_size = sizeof(*outer_hdr) + inner_len; + combined_data = vmalloc(combined_size); + if (!combined_data) { + bt_dev_warn(hdev, + "QCA Failed to allocate memory for file: %s", + calib_name); + release_firmware(calib_fw); + goto skip_combination; + } + + outer_hdr = (struct tlv_type_hdr *)combined_data; + /* high 24 bits = payload length, low 8 bits = type */ + outer_hdr->type_len = cpu_to_le32((inner_len << 8) | 4); + memcpy(combined_data + sizeof(*outer_hdr), data, size); + memcpy(combined_data + sizeof(*outer_hdr) + size, + calib_fw->data, calib_fw->size); + release_firmware(calib_fw); + vfree(data); + data = combined_data; + size = combined_size; +skip_combination: + ; + } + ret = qca_tlv_check_data(hdev, config, data, size, soc_type); if (ret) goto out; From 5bcad3b30d5f39c9cb152f0c761eb7360c1521d8 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Wed, 27 May 2026 12:36:24 +0530 Subject: [PATCH 0804/1058] Revert "firmware: qcom: scm: Allow QSEECOM on Glymur CRD" Adding glymur-crd to the QSEECOM allowlist causes qcom_scm to fully initialize at early boot, which sets up uefisecapp and registers EFI variable operations. This makes efi_has_tpm2() succeed by reading the LoaderTpm2ActivePcrBanks EFI variable, satisfying ConditionSecurity=tpm2 in systemd. As a result, systemd activates tpm2.target which unconditionally waits for /dev/tpm0 and /dev/tpmrm0. systemd waits the full 90-second timeout for each of the two TPM device units, pushing total boot time beyond 2 minutes. Revert until TPM driver in place and /dev/tpm0 node is created. This reverts commit 87a1698cb80650e47b41ca78a78ce06870cba631. Signed-off-by: Salendarsingh Gaud --- drivers/firmware/qcom/qcom_scm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 760a027bb5f3b..1a2b1976ae2ed 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2311,7 +2311,6 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "microsoft,denali", }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, - { .compatible = "qcom,glymur-crd" }, { .compatible = "qcom,hamoa-iot-evk" }, { .compatible = "qcom,mahua-crd" }, { .compatible = "qcom,purwa-iot-evk" }, From ecc126013f9aac2681125eddbe60f7fa40beeaa3 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Mon, 22 Jun 2026 11:34:44 +0530 Subject: [PATCH 0805/1058] WORKAROUND: arch: arm64: qcom: glymur-crd: Disable PCIe6 instance On compute targets, PCIe is dependent on the UEFI. In UEFI, when a PCIe link-up fails on a given root port, the default behavior is to power down that root port. The power-down sequence disables the PHY, removes all clock votes, and drops the Interconnect Bandwidth (ICB) votes that were applied in UEFI for that PCIe controller. The HLOS PCIe driver when probes the PCIe6 root port, but probe fails because the PHY is already powered down and there is no PHY bring-up sequence in HLOS for any controller. Since PCIe probe fails, the Interconnect driver's sync_state callback never gets invoked. As a result, the max boot votes applied to other peripherals are never released or reduced, keeping the system stuck at max bandwidth votes and causing the sync state errors observed, this also blocks XO shutdown. Fix this temporarly, by disabling pcie6 now as modem is not functional in this release. we will revert this after finding proper fix. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index e784b538f42e1..2a507d1692232 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -522,14 +522,14 @@ pinctrl-0 = <&pcie6_default>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; }; &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; - status = "okay"; + status = "disabled"; }; &pcie6_port0 { From bd228743521239ce052e52a798583874bbdc55b6 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 3 Mar 2026 18:26:31 +0530 Subject: [PATCH 0806/1058] arm64: dts: qcom: Introduce Shikra Soc base dtsi Introduce the initial support for the Qualcomm Shikra SoC. The initial submission enables support for: - CPUs nodes with PSCI idle states - Interrupt-controller - Top Level Mode Multiplexer (TLMM) - System Timer Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 245 +++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra.dtsi diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi new file mode 100644 index 0000000000000..8be8b06f3e233 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + }; + + cpu1: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + }; + + cpu2: cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x200>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + }; + + cpu3: cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a78c"; + reg = <0x0 0x300>; + enable-method = "psci"; + next-level-cache = <&l2_3>; + capacity-dmips-mhz = <1946>; + dynamic-power-coefficient = <486>; + + l2_3: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&l3>; + }; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + + core1 { + cpu = <&cpu1>; + }; + + core2 { + cpu = <&cpu2>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu3>; + }; + }; + }; + + l3: l3-cache { + compatible = "cache"; + cache-level = <3>; + cache-unified; + }; + }; + + memory@a0000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + }; + + soc: soc@0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <2>; + dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + + tlmm: pinctrl@500000 { + compatible = "qcom,shikra-tlmm"; + reg = <0x0 0x00500000 0x0 0x800000>; + + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + gpio-ranges = <&tlmm 0 0 165>; + + qup_uart0_default: qup-uart0-default-state { + pins = "gpio0", "gpio1"; + function = "qup0_se1"; + drive-strength = <2>; + bias-disable; + }; + }; + + sram@c11e000 { + compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; + reg = <0x0 0x0c11e000 0x0 0x1000>; + ranges = <0x0 0x0 0x0c11e000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + pil-reloc@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; + }; + + intc: interrupt-controller@f200000 { + compatible = "arm,gic-v3"; + reg = <0x0 0xf200000 0x0 0x10000>, /* GICD */ + <0x0 0xf240000 0x0 0x80000>; /* GICR * 4 regions */ + + interrupts = ; + + #interrupt-cells = <3>; + interrupt-controller; + + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x20000>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + }; + + timer@f420000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x0f420000 0x0 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x10000000>; + + frame@f421000 { + reg = <0x0f421000 0x1000>, + <0x0f422000 0x1000>; + frame-number = <0>; + interrupts = , + ; + }; + + frame@f423000 { + reg = <0x0f423000 0x1000>; + frame-number = <1>; + interrupts = ; + status = "disabled"; + }; + + frame@f425000 { + reg = <0x0f425000 0x1000>; + frame-number = <2>; + interrupts = ; + status = "disabled"; + }; + + frame@f427000 { + reg = <0x0f427000 0x1000>; + frame-number = <3>; + interrupts = ; + status = "disabled"; + }; + + frame@f429000 { + reg = <0x0f429000 0x1000>; + frame-number = <4>; + interrupts = ; + status = "disabled"; + }; + + frame@f42b000 { + reg = <0x0f42b000 0x1000>; + frame-number = <5>; + interrupts = ; + status = "disabled"; + }; + + frame@f42d000 { + reg = <0x0f42d000 0x1000>; + frame-number = <6>; + interrupts = ; + status = "disabled"; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + + interrupts = , + , + , + ; + }; +}; From 08b96bb6c106b741925cd1571172c35d58bc113d Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 3 Mar 2026 19:05:13 +0530 Subject: [PATCH 0807/1058] arm64: dts: qcom: Add Shikra IoT SoM platforms The Shikra SoM is a compact compute module integrating the SoC and essential components optimized for IoT applications, designed to mount on carrier boards. Shikra supports three SoM variants: two retail options (with and without modem) and one industrial variant , represented by the following device trees: - shikra-cqm-som.dtsi : Retail SoM with modem - shikra-cqs-som.dtsi : Retail SoM without modem - shikra-iqs-som.dtsi : Industrial SoM without modem Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 8 ++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 8 ++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 8 ++++++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi new file mode 100644 index 0000000000000..75ae79daf3b45 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "shikra.dtsi" + +/* Modem, Cocos + Kunlun PMIC */ diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi new file mode 100644 index 0000000000000..be745fe517e88 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "shikra.dtsi" + +/* APQ (No Modem), Cocos + Kunlun PMIC */ diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi new file mode 100644 index 0000000000000..a916caa73d823 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "shikra.dtsi" + +/* APQ (No Modem), Wailua PMIC */ diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 8be8b06f3e233..0cc182cf33aa2 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -122,7 +122,7 @@ tlmm: pinctrl@500000 { compatible = "qcom,shikra-tlmm"; - reg = <0x0 0x00500000 0x0 0x800000>; + reg = <0x0 0x00500000 0x0 0x700000>; interrupts = ; From 53a8ad91a5da85a7ec63be6c02570d06039291d3 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 3 Mar 2026 19:37:13 +0530 Subject: [PATCH 0808/1058] arm64: dts: qcom: Add Shikra EVK boards Add device trees for the Shikra EVK platform, which combines Shikra SoM with a common carrier board. Introduce DTS files for CQM, CQS and IQS EVK variants: - shikra-cqm-evk.dts - shikra-cqs-evk.dts - shikra-iqs-evk.dts Also add a shared include file, shikra-evk.dtsi, which contains the common daughter card nodes used across Shikra EVK variants. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 22 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 22 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 14 +++++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 22 +++++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts create mode 100644 arch/arm64/boot/dts/qcom/shikra-evk.dtsi create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..a9e9d829fb962 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -334,6 +334,9 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm850-huawei-matebook-e-2019.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-samsung-w737.dtb dtb-$(CONFIG_ARCH_QCOM) += sdx75-idp.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts new file mode 100644 index 0000000000000..98fd302e932c5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-cqm-som.dtsi" +#include "shikra-evk.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Shikra CQM EVK"; + compatible = "qcom,shikra-cqm-evk", "qcom,shikra-cqm-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts new file mode 100644 index 0000000000000..595c9e986f68b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-cqs-som.dtsi" +#include "shikra-evk.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Shikra CQS EVK"; + compatible = "qcom,shikra-cqs-evk", "qcom,shikra-cqs-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi new file mode 100644 index 0000000000000..cf7460e1125d6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* Common daughter cards nodes to be added: + * QPS615 DC + * MIC DC + * Display DC + * Camera DC + * USB hub DC + * Sensor DC + * NFC DC + */ diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts new file mode 100644 index 0000000000000..394261d042c2f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-iqs-som.dtsi" +#include "shikra-evk.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; + compatible = "qcom,shikra-iqs-evk", "qcom,shikra-iqs-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; From 70af636a2907e527d3d4307f9755b98046121001 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 24 Mar 2026 20:38:37 +0530 Subject: [PATCH 0809/1058] arm64: dts: qcom: Shikra: Add reserved memory nodes Add the reserved memory nodes for Shikra. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 100 ++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 0cc182cf33aa2..91ce4163c1216 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -107,9 +107,107 @@ method = "smc"; }; - reserved-memory { + reserved_memory: reserved-memory { #address-cells = <2>; #size-cells = <2>; + ranges; + + hyp_mem: hyp@80000000 { + reg = <0x0 0x80000000 0x0 0x1600000>; + no-map; + }; + + xblboot_mem: xblboot@85e00000 { + reg = <0x0 0x85e00000 0x0 0x100000>; + no-map; + }; + + secdata_apss_mem: secdata-apss@85fff000 { + reg = <0x0 0x85fff000 0x0 0x1000>; + no-map; + }; + + smem_mem: smem_region@86000000 { + compatible = "qcom,smem"; + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + }; + + audio_heap_mem: audio-heap@86200000 { + reg = <0x0 0x86200000 0x0 0x100000>; + no-map; + }; + + pvm_fw_mem: pvm-fw@86300000 { + reg = <0x0 0x86300000 0x0 0x100000>; + no-map; + }; + + /* UEFI region at 0x9F400000 is reclaimed by Linux */ + tz_stat_mem: tz-stat@a0000000 { + reg = <0x0 0xa0000000 0x0 0x100000>; + no-map; + }; + + qtee_mem: qtee@a1300000 { + reg = <0x0 0xa1300000 0x0 0x500000>; + no-map; + }; + + tz_apps_mem: tz-apps@a1800000 { + reg = <0x0 0xa1800000 0x0 0x2100000>; + no-map; + }; + + mpss_wlan_mem: mpss-wlan@ab000000 { + reg = <0x0 0xab000000 0x0 0x6e00000>; + no-map; + }; + + wlan_mem: wlan@b2300000 { + reg = <0x0 0xb2300000 0x0 0x100000>; + no-map; + }; + + cdsp_mem: cdsp@b2400000 { + reg = <0x0 0xb2400000 0x0 0x1900000>; + no-map; + }; + + gpu_micro_code_mem: gpu-micro-code@b3d00000 { + reg = <0x0 0xb3d00000 0x0 0x2000>; + no-map; + }; + + video_mem: video@b3d02000 { + reg = <0x0 0xb3d02000 0x0 0x700000>; + no-map; + }; + + lmcu_mem: lmcu@b4402000 { + reg = <0x0 0xb4402000 0x0 0x300000>; + no-map; + }; + + lmcu_dtb_mem: lmcu-dtb@b4702000 { + reg = <0x0 0xb4702000 0x0 0x40000>; + no-map; + }; + + /* Linux kernel image is loaded at 0xB5000000 */ + trust_ui_vm_mem: trust-ui-vm@f3800000 { + compatible = "shared-dma-pool"; + reg = <0x0 0xf3800000 0x0 0x4000000>; + alignment = <0x0 0x400000>; + reusable; + }; + + oem_vm_mem: oem-vm@f7c00000 { + compatible = "shared-dma-pool"; + reg = <0x0 0xf7c00000 0x0 0x4c00000>; + alignment = <0x0 0x400000>; + reusable; + }; }; soc: soc@0 { From 8aca1c977c1527b2b8727e27b9f761e71a9cb733 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 26 Mar 2026 12:36:51 +0530 Subject: [PATCH 0810/1058] arm64: dts: qcom: Shikra: add smmu nodes Add the apps and adreno smmu node as found in Shikra SoC. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 91 ++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 91ce4163c1216..95875107dce08 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -240,6 +240,23 @@ }; }; + adreno_smmu: iommu@59a0000 { + compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x059a0000 0x0 0x10000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + }; + sram@c11e000 { compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; reg = <0x0 0x0c11e000 0x0 0x1000>; @@ -254,6 +271,80 @@ }; }; + apps_smmu: iommu@c600000 { + compatible = "qcom,shikra-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x0c600000 0x0 0x80000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + intc: interrupt-controller@f200000 { compatible = "arm,gic-v3"; reg = <0x0 0xf200000 0x0 0x10000>, /* GICD */ From c39b84035d19edde7cd3c4cd11dc955b474bbe02 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Mon, 16 Mar 2026 21:08:23 +0530 Subject: [PATCH 0811/1058] dt-bindings: mailbox: qcom,apcs-kpss-global: Add Shikra compatible Add qcom,shikra-apcs-hmss-global for the APCS mailbox binding. This avoids undocumented-compatible warnings from checkpatch and keeps schema constraints aligned for this target. Signed-off-by: Vishnu Santhosh --- .../devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml index 1b4ef0688ca79..01d6eaefe165e 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml @@ -66,6 +66,7 @@ properties: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global reg: maxItems: 1 @@ -239,6 +240,7 @@ allOf: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global then: properties: clocks: false From 85baaadc7c543c62afeb1b9987934452d522b8c6 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Mon, 16 Mar 2026 21:08:23 +0530 Subject: [PATCH 0812/1058] arm64: dts: qcom: Add RPM GLINK transport nodes Add the RPM message RAM SRAM region and APCS HMSS global mailbox controller, and wire them up to a new glink-edge node. The rpm_msg_ram node exposes the shared SRAM used for GLINK FIFOs and includes the apss_mpm sub-node for the MPM sleep counter. The `qcom,glink-rpm` transport uses: - `qcom,rpm-msg-ram` for shared GLINK FIFOs - APCS mailbox channel 0 for kick/notify This enables RPM GLINK-based inter-processor communication on Shikra. Signed-off-by: Vishnu Santhosh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 95875107dce08..bd977691bbde0 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -107,6 +107,17 @@ method = "smc"; }; + rpm: remoteproc { + compatible = "qcom,shikra-rpm-proc", "qcom,rpm-proc"; + + glink-edge { + compatible = "qcom,glink-rpm"; + interrupts = ; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + mboxes = <&apcs_glb 0>; + }; + }; + reserved_memory: reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -240,6 +251,19 @@ }; }; + rpm_msg_ram: sram@45f0000 { + compatible = "qcom,rpm-msg-ram", "mmio-sram"; + reg = <0x0 0x045f0000 0x0 0x7000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x045f0000 0x7000>; + + apss_mpm: sram@1b8 { + reg = <0x1b8 0x48>; + }; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; @@ -363,6 +387,12 @@ ranges; }; + apcs_glb: mailbox@f400000 { + compatible = "qcom,shikra-apcs-hmss-global"; + reg = <0x0 0x0f400000 0x0 0x1000>; + #mbox-cells = <1>; + }; + timer@f420000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x0f420000 0x0 0x1000>; From 590151f8e11563ea821b9b88a614734792f3446b Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 27 Mar 2026 15:43:50 +0530 Subject: [PATCH 0813/1058] arm64: dts: qcom: Shikra: Add qfprom node Add qfprom node and its properties for Shikra SoC. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index bd977691bbde0..6336af856d200 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -116,6 +116,30 @@ qcom,rpm-msg-ram = <&rpm_msg_ram>; mboxes = <&apcs_glb 0>; }; + + mpm: interrupt-controller { + compatible = "qcom,mpm"; + qcom,rpm-msg-ram = <&apss_mpm>; + interrupts = ; + mboxes = <&apcs_glb 1>; + interrupt-controller; + #interrupt-cells = <2>; + #power-domain-cells = <0>; + interrupt-parent = <&intc>; + qcom,mpm-pin-count = <95>; + qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */ + <12 422>, /* DWC3 ss_phy_irq */ + <58 272>, /* QUSB2_PHY dmse_hv_vddmx */ + <59 273>, /* QUSB2_PHY dpse_hv_vddmx */ + <86 183>, /* MPM wake, SPMI */ + <90 157>, /* QUSB2_PHY DM */ + <91 158>; /* QUSB2_PHY DP */ + }; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm"; + qcom,glink-channels = "rpm_requests"; + }; }; reserved_memory: reserved-memory { @@ -242,6 +266,7 @@ #interrupt-cells = <2>; gpio-ranges = <&tlmm 0 0 165>; + wakeup-parent = <&mpm>; qup_uart0_default: qup-uart0-default-state { pins = "gpio0", "gpio1"; @@ -251,6 +276,18 @@ }; }; + qfprom: efuse@1b40000 { + compatible = "qcom,shikra-qfprom", "qcom,qfprom"; + reg = <0x0 0x01b40000 0x0 0x700>; + #address-cells = <1>; + #size-cells = <1>; + + gpu_speed_bin: gpu-speed-bin@6006 { + reg = <0x6006 0x2>; + bits = <5 8>; + }; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; @@ -264,6 +301,11 @@ }; }; + sram@4690000 { + compatible = "qcom,rpm-stats"; + reg = <0x0 0x04690000 0x0 0x14000>; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; From 0f2ee764c897f7f0346d209963b741a68a73d57a Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Mon, 30 Mar 2026 15:48:02 +0530 Subject: [PATCH 0814/1058] arm64: dts: qcom: Move rpm_requests in glink-edge node Move rpm_requests node to under glink-edge node. Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/shikra.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 6336af856d200..023630d77194b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -115,6 +115,11 @@ interrupts = ; qcom,rpm-msg-ram = <&rpm_msg_ram>; mboxes = <&apcs_glb 0>; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm"; + qcom,glink-channels = "rpm_requests"; + }; }; mpm: interrupt-controller { @@ -135,11 +140,6 @@ <90 157>, /* QUSB2_PHY DM */ <91 158>; /* QUSB2_PHY DP */ }; - - rpm_requests: rpm-requests { - compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm"; - qcom,glink-channels = "rpm_requests"; - }; }; reserved_memory: reserved-memory { From 8b34cd9ee927fae3c8dcb891a764e3545167a358 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 13 Mar 2026 18:02:14 +0530 Subject: [PATCH 0815/1058] arm64: dts: qcom: Add GCC and RPMCC node support Add support for RPMCC and GCC nodes on Shikra platforms. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 023630d77194b..13ab73c662d73 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -3,6 +3,8 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include +#include #include / { @@ -11,6 +13,20 @@ #address-cells = <2>; #size-cells = <2>; + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32764>; + #clock-cells = <0>; + }; + }; + cpus { #address-cells = <2>; #size-cells = <0>; @@ -119,6 +135,13 @@ rpm_requests: rpm-requests { compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; + + rpmcc: clock-controller { + compatible = "qcom,rpmcc-shikra", "qcom,rpmcc"; + clocks = <&xo_board>; + clock-names = "xo"; + #clock-cells = <1>; + }; }; }; @@ -276,6 +299,22 @@ }; }; + gcc: clock-controller@1400000 { + compatible = "qcom,shikra-gcc"; + reg = <0x0 0x01400000 0x0 0x1f0000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + qfprom: efuse@1b40000 { compatible = "qcom,shikra-qfprom", "qcom,qfprom"; reg = <0x0 0x01b40000 0x0 0x700>; From eec3bae65dfe00e15f1b18fe49262a2aab39f176 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 30 Mar 2026 16:31:38 +0530 Subject: [PATCH 0816/1058] arm64: dts: qcom: Add SPMI bus controller for Shikra Add spmi-pmic-arb device for the SPMI PMIC arbiter found on shikra. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 13ab73c662d73..446da2058901a 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -327,6 +327,28 @@ }; }; + spmi_bus: spmi@1c40000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x01c40000 0x0 0x1100>, + <0x0 0x01e00000 0x0 0x2000000>, + <0x0 0x03e00000 0x0 0x100000>, + <0x0 0x03f00000 0x0 0xa0000>, + <0x0 0x01c0a000 0x0 0x26000>; + reg-names = "core", + "chnls", + "obsrvr", + "intr", + "cnfg"; + interrupts-extended = <&mpm 86 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "periph_irq"; + interrupt-controller; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <0>; + qcom,channel = <0>; + qcom,ee = <0>; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; From 0be31c411bf4304dadc609149154f614681f165f Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 30 Mar 2026 18:13:38 +0530 Subject: [PATCH 0817/1058] arm64: dts: qcom: Add RPM power domain controller for shikra Add the RPM SMD power domain controller node for Shikra with a complete OPP table covering all 8 voltage corners from MIN_SVS to TURBO_NO_CPR. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra.dtsi | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 446da2058901a..fb7a38ddfbbe1 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include / { interrupt-parent = <&intc>; @@ -142,6 +143,48 @@ clock-names = "xo"; #clock-cells = <1>; }; + + rpmpd: power-controller { + compatible = "qcom,shikra-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmpd_opp_min_svs: opp1 { + opp-level = ; + }; + + rpmpd_opp_low_svs: opp2 { + opp-level = ; + }; + + rpmpd_opp_svs: opp3 { + opp-level = ; + }; + + rpmpd_opp_svs_plus: opp4 { + opp-level = ; + }; + + rpmpd_opp_nom: opp5 { + opp-level = ; + }; + + rpmpd_opp_nom_plus: opp6 { + opp-level = ; + }; + + rpmpd_opp_turbo: opp7 { + opp-level = ; + }; + + rpmpd_opp_turbo_plus: opp8 { + opp-level = ; + }; + }; + }; }; }; From fa7b0cd4de4b16c7c041bcf2007d40416c69493c Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 30 Mar 2026 16:32:39 +0530 Subject: [PATCH 0818/1058] arm64: dts: qcom: Add regulator for Retail and Industrial SOM variants Add RPM regulator for the Shikra Retail (CQM/CQS) SOM variants using pm4125-regulators with S1-S4 buck switchers and L1-L22 LDOs, and for the Industrial (IQS) SOM variant using pm8150-regulators with S4-S9 buck switchers and L1-L18 LDOs. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 131 +++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 131 +++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 120 +++++++++++++++++ 3 files changed, 382 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 75ae79daf3b45..79ea476c7c4a6 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -6,3 +6,134 @@ #include "shikra.dtsi" /* Modem, Cocos + Kunlun PMIC */ + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm2250-regulators"; + + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_s2: s2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_s4: s4 { + regulator-min-microvolt = <640000>; + regulator-max-microvolt = <1414000>; + }; + + pm4125_l1: l1 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l2: l2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_l3: l3 { + regulator-min-microvolt = <570000>; + regulator-max-microvolt = <650000>; + }; + + pm4125_l4: l4 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l5: l5 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l6: l6 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm4125_l7: l7 { + regulator-min-microvolt = <664000>; + regulator-max-microvolt = <664000>; + }; + + pm4125_l8: l8 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l10: l10 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l11: l11 { + regulator-min-microvolt = <970000>; + regulator-max-microvolt = <1150000>; + }; + + pm4125_l12: l12 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + }; + + pm4125_l13: l13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_l14: l14 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2000000>; + }; + + pm4125_l16: l16 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <2000000>; + }; + + pm4125_l17: l17 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l18: l18 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l19: l19 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l20: l20 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l21: l21 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l22: l22 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index be745fe517e88..2434c997173e2 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -6,3 +6,134 @@ #include "shikra.dtsi" /* APQ (No Modem), Cocos + Kunlun PMIC */ + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm2250-regulators"; + + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_s2: s2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_s4: s4 { + regulator-min-microvolt = <640000>; + regulator-max-microvolt = <1414000>; + }; + + pm4125_l1: l1 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l2: l2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_l3: l3 { + regulator-min-microvolt = <570000>; + regulator-max-microvolt = <650000>; + }; + + pm4125_l4: l4 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l5: l5 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l6: l6 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm4125_l7: l7 { + regulator-min-microvolt = <664000>; + regulator-max-microvolt = <664000>; + }; + + pm4125_l8: l8 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l10: l10 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l11: l11 { + regulator-min-microvolt = <970000>; + regulator-max-microvolt = <1150000>; + }; + + pm4125_l12: l12 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + }; + + pm4125_l13: l13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_l14: l14 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1950000>; + }; + + pm4125_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2000000>; + }; + + pm4125_l16: l16 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <2000000>; + }; + + pm4125_l17: l17 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l18: l18 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l19: l19 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + }; + + pm4125_l20: l20 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l21: l21 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l22: l22 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index a916caa73d823..9581f98b7d08e 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -6,3 +6,123 @@ #include "shikra.dtsi" /* APQ (No Modem), Wailua PMIC */ +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm8150-regulators"; + + pm8150_s4: s4 { + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <2040000>; + }; + + pm8150_s5: s5 { + regulator-min-microvolt = <1574000>; + regulator-max-microvolt = <2040000>; + }; + + pm8150_s6: s6 { + regulator-min-microvolt = <382000>; + regulator-max-microvolt = <1352000>; + }; + + pm8150_s7: s7 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm8150_s8: s8 { + regulator-min-microvolt = <570000>; + regulator-max-microvolt = <650000>; + }; + + pm8150_l1: l1 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l2: l2 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3300000>; + }; + + pm8150_l3: l3 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l4: l4 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + }; + + pm8150_l5: l5 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm8150_l6: l6 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm8150_l7: l7 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <2000000>; + }; + + pm8150_l8: l8 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm8150_l10:l10{ + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l11:l11{ + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l12:l12{ + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1950000>; + }; + + pm8150_l13:l13{ + regulator-min-microvolt = <2921000>; + regulator-max-microvolt = <3230000>; + }; + + pm8150_l14:l14{ + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1910000>; + }; + + pm8150_l15:l15{ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + pm8150_l16:l16{ + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l17:l17{ + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l18:l18{ + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <728000>; + }; + }; +}; From 597266b969497e25d1c220b15413c46168a56099 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 1 Apr 2026 19:02:52 +0530 Subject: [PATCH 0819/1058] arm64: dts: qcom: shikra: Add watchdog node Add the watchdog node for Shikra SoC. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index fb7a38ddfbbe1..faa6c347301ad 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -539,6 +539,14 @@ #mbox-cells = <1>; }; + watchdog@f410000 { + compatible = "qcom,apss-wdt-shikra", "qcom,kpss-wdt"; + reg = <0x0 0x0f410000 0x0 0x1000>; + interrupts = , + ; + clocks = <&sleep_clk>; + }; + timer@f420000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x0f420000 0x0 0x1000>; From d3a479f07ee01facd6268894cf9267a5605512d5 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 3 Apr 2026 19:14:59 +0530 Subject: [PATCH 0820/1058] arm64: dts: qcom: shikra: Add TCSR mutex hwlock support Describe the TCSR mutex hwlock controller and reference it from the SMEM node to enable proper hardware locking on Shikra. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index faa6c347301ad..eda7a36d7f97b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -232,6 +232,8 @@ compatible = "qcom,smem"; reg = <0x0 0x86000000 0x0 0x200000>; no-map; + + hwlocks = <&tcsr_mutex 3>; }; audio_heap_mem: audio-heap@86200000 { @@ -319,6 +321,12 @@ dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + tcsr_mutex: syscon@340000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x0 0x00340000 0x0 0x20000>; + #hwlock-cells = <1>; + }; + tlmm: pinctrl@500000 { compatible = "qcom,shikra-tlmm"; reg = <0x0 0x00500000 0x0 0x700000>; From ffcf723c8525871fa6f0f89e0f26dd4cfda36641 Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 1 Apr 2026 16:27:25 +0530 Subject: [PATCH 0821/1058] arm64: dts: msm: add interconnect devices for Shikra Add interconnect devices for config_noc, system_noc, mc_virt, clk_virt, mem_noc, mmnrt_virt and mmrt_virt. This will allow consumers to get their path and set bandwidth constraints on them. Signed-off-by: Raviteja Laggyshetty --- arch/arm64/boot/dts/qcom/shikra.dtsi | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index eda7a36d7f97b..cdc678029fafa 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -350,6 +352,14 @@ }; }; + mem_noc: interconnect@d00000 { + compatible = "qcom,shikra-mem-noc-core"; + reg = <0x0 0x00d00000 0x0 0x43080>; + clocks = <&gcc GCC_DDRSS_GPU_AXI_CLK>; + clock-names = "gpu_axi"; + #interconnect-cells = <2>; + }; + gcc: clock-controller@1400000 { compatible = "qcom,shikra-gcc"; reg = <0x0 0x01400000 0x0 0x1f0000>; @@ -366,6 +376,46 @@ #power-domain-cells = <1>; }; + system_noc: interconnect@1880000 { + compatible = "qcom,shikra-sys-noc"; + reg = <0x0 0x01880000 0x0 0x6a080>; + clocks = <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>, + <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>, + <&gcc GCC_SYS_NOC_USB2_PRIM_AXI_CLK>, + <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>; + clock-names = "emac0_axi", + "emac1_axi", + "usb2_axi", + "usb3_axi"; + #interconnect-cells = <2>; + + clk_virt: interconnect-clk { + compatible = "qcom,shikra-clk-virt"; + #interconnect-cells = <2>; + }; + + mc_virt: interconnect-mc { + compatible = "qcom,shikra-mc-virt"; + #interconnect-cells = <2>; + }; + + mmrt_virt: interconnect-mmrt { + compatible = "qcom,shikra-mmrt-virt"; + #interconnect-cells = <2>; + }; + + mmnrt_virt: interconnect-mmnrt { + compatible = "qcom,shikra-mmnrt-virt"; + #interconnect-cells = <2>; + }; + }; + + config_noc: interconnect@1900000 { + compatible = "qcom,shikra-config-noc"; + reg = <0x0 0x01900000 0x0 0x8080>; + #interconnect-cells = <2>; + }; + qfprom: efuse@1b40000 { compatible = "qcom,shikra-qfprom", "qcom,qfprom"; reg = <0x0 0x01b40000 0x0 0x700>; From cbba3c6c276d8ea0a8d42eb09a3cf841872e4f0f Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 3 Apr 2026 19:36:11 +0530 Subject: [PATCH 0822/1058] arm64: dts: qcom: shikra: Add download mode support Add the SCM firmware node and TCSR syscon required to support download mode on Shikra. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index cdc678029fafa..e8fa439d4a4fa 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -110,6 +110,15 @@ }; }; + firmware { + scm { + compatible = "qcom,scm-shikra", "qcom,scm"; + qcom,dload-mode = <&tcsr_regs 0x13000>; + interconnects = <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + }; + }; + memory@a0000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ @@ -329,6 +338,11 @@ #hwlock-cells = <1>; }; + tcsr_regs: syscon@3c0000 { + compatible = "qcom,shikra-tcsr", "syscon"; + reg = <0x0 0x003c0000 0x0 0x40000>; + }; + tlmm: pinctrl@500000 { compatible = "qcom,shikra-tlmm"; reg = <0x0 0x00500000 0x0 0x700000>; From d69a8d611bdcf66ef31583b495c9a9aa657a870b Mon Sep 17 00:00:00 2001 From: Xueyao An Date: Thu, 26 Mar 2026 10:44:58 +0800 Subject: [PATCH 0823/1058] arm64: dts: qcom: Add QUPv3 UART console node for shikra Enable console support for shikra. Signed-off-by: Xueyao An --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 5 +++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 5 +++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 5 +++ arch/arm64/boot/dts/qcom/shikra.dtsi | 38 ++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 98fd302e932c5..fec2e2fff10ac 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -14,9 +14,14 @@ chassis-type = "embedded"; aliases { + serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; }; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 595c9e986f68b..26a69057b6120 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -14,9 +14,14 @@ chassis-type = "embedded"; aliases { + serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; }; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 394261d042c2f..fc2cb325e3abb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -14,9 +14,14 @@ chassis-type = "embedded"; aliases { + serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; }; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index e8fa439d4a4fa..0bf3f5bc46bd9 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -360,7 +360,7 @@ qup_uart0_default: qup-uart0-default-state { pins = "gpio0", "gpio1"; - function = "qup0_se1"; + function = "qup0_se0"; drive-strength = <2>; bias-disable; }; @@ -677,6 +677,42 @@ status = "disabled"; }; }; + + qupv3_0: geniqup@4ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x04ac0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + uart0: serial@4a80000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x04a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart0_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + }; }; timer { From 0f83093d4d6fec7b39ae4424c31a7e23632f7a15 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Tue, 7 Apr 2026 18:55:41 +0530 Subject: [PATCH 0824/1058] arm64: dts: qcom: Add eMMC support for shikra SoC Add support for eMMC on shikra SoC and enable the required pinctrl configurations. Signed-off-by: Monish Chunara --- arch/arm64/boot/dts/qcom/shikra.dtsi | 116 +++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 0bf3f5bc46bd9..8bccbb3ff07f5 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -364,6 +365,56 @@ drive-strength = <2>; bias-disable; }; + + sdc1_state_on: sdc1-on-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <6>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <6>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <6>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc1_state_off: sdc1-off-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <2>; + bias-bus-hold; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <2>; + bias-bus-hold; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <2>; + bias-bus-hold; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-bus-hold; + }; + }; }; mem_noc: interconnect@d00000 { @@ -482,6 +533,71 @@ reg = <0x0 0x04690000 0x0 0x14000>; }; + sdhc_1: mmc@4744000 { + compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5"; + + reg = <0x0 0x04744000 0x0 0x1000>, + <0x0 0x04745000 0x0 0x1000>; + reg-names = "hc", + "cqhci"; + + iommus = <&apps_smmu 0xc0 0x0>; + + interrupts = , + ; + interrupt-names = "hc_irq", + "pwr_irq"; + + clocks = <&gcc GCC_SDCC1_AHB_CLK>, + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "core", + "xo"; + + interconnects = <&system_noc MASTER_SDCC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>, + <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_SDCC_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "sdhc-ddr", + "cpu-sdhc"; + + power-domains = <&rpmpd RPMHPD_CX>; + operating-points-v2 = <&sdhc1_opp_table>; + + qcom,dll-config = <0x000f642c>; + qcom,ddr-config = <0x80040868>; + + bus-width = <8>; + + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + + resets = <&gcc GCC_SDCC1_BCR>; + + status = "disabled"; + + sdhc1_opp_table: opp-table-1 { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmpd_opp_low_svs>; + opp-peak-kBps = <250000 133320>; + opp-avg-kBps = <104000 0>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <800000 300000>; + opp-avg-kBps = <400000 0>; + }; + }; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; From 0f6e20bfed88a24c46de6b6d29baae3a101e2553 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Tue, 7 Apr 2026 18:58:23 +0530 Subject: [PATCH 0825/1058] arm64: dts: qcom: Enable eMMC for shikra EVK Enable eMMC for shikra CQS, CQM and IQS EVK variants. Signed-off-by: Monish Chunara --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 17 +++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 17 +++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index fec2e2fff10ac..8b4b51f68e4bc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -14,6 +14,7 @@ chassis-type = "embedded"; aliases { + mmc0 = &sdhc_1; serial0 = &uart0; }; @@ -22,6 +23,22 @@ }; }; +&sdhc_1 { + vmmc-supply = <&pm4125_l20>; + vqmmc-supply = <&pm4125_l14>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 26a69057b6120..7f82f58007646 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -14,6 +14,7 @@ chassis-type = "embedded"; aliases { + mmc0 = &sdhc_1; serial0 = &uart0; }; @@ -22,6 +23,22 @@ }; }; +&sdhc_1 { + vmmc-supply = <&pm4125_l20>; + vqmmc-supply = <&pm4125_l14>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index fc2cb325e3abb..52aeab4ee80fc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -14,6 +14,7 @@ chassis-type = "embedded"; aliases { + mmc0 = &sdhc_1; serial0 = &uart0; }; @@ -22,6 +23,22 @@ }; }; +&sdhc_1 { + vmmc-supply = <&pm8150_l17>; + vqmmc-supply = <&pm8150_s4>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + &uart0 { status = "okay"; }; From e506c5d64bedb31bada8cdecd42ebf841ea0aa76 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Tue, 7 Apr 2026 20:42:20 +0530 Subject: [PATCH 0826/1058] arm64: dts: qcom: Add SD Card support for shikra SoC Add support for SD card on shikra SoC and enable the required pinctrl configurations. Signed-off-by: Monish Chunara --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 18 ++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 18 ++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 18 ++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 91 +++++++++++++++++++++ 4 files changed, 145 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 8b4b51f68e4bc..2b7e2f236c465 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -7,6 +7,7 @@ #include "shikra-cqm-som.dtsi" #include "shikra-evk.dtsi" +#include / { model = "Qualcomm Technologies, Inc. Shikra CQM EVK"; @@ -15,6 +16,7 @@ aliases { mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; }; @@ -39,6 +41,22 @@ status = "okay"; }; +&sdhc_2 { + vmmc-supply = <&pm4125_l21>; + vqmmc-supply = <&pm4125_l4>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 7f82f58007646..3022ab4ccffeb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -7,6 +7,7 @@ #include "shikra-cqs-som.dtsi" #include "shikra-evk.dtsi" +#include / { model = "Qualcomm Technologies, Inc. Shikra CQS EVK"; @@ -15,6 +16,7 @@ aliases { mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; }; @@ -39,6 +41,22 @@ status = "okay"; }; +&sdhc_2 { + vmmc-supply = <&pm4125_l21>; + vqmmc-supply = <&pm4125_l4>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 52aeab4ee80fc..60951524844b2 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -7,6 +7,7 @@ #include "shikra-iqs-som.dtsi" #include "shikra-evk.dtsi" +#include / { model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; @@ -15,6 +16,7 @@ aliases { mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; }; @@ -39,6 +41,22 @@ status = "okay"; }; +&sdhc_2 { + vmmc-supply = <&pm8150_l10>; + vqmmc-supply = <&pm8150_l2>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 8bccbb3ff07f5..83ebb433bb223 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -415,6 +415,53 @@ bias-bus-hold; }; }; + + sdc2_default: sdc2-default-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <14>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <14>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <14>; + bias-pull-up; + }; + }; + + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + sdc2_card_det_n: sd-card-det-n-state { + pins = "gpio89"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; mem_noc: interconnect@d00000 { @@ -598,6 +645,50 @@ }; }; + sdhc_2: mmc@4784000 { + compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x0 0x4784000 0x0 0x1000>; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + bus-width = <4>; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "core", "xo"; + + qcom,dll-config = <0x0007442c>; + qcom,ddr-config = <0x80040868>; + + iommus = <&apps_smmu 0x0a0 0x0>; + + interconnects = <&system_noc MASTER_SDCC_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>, + <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_SDCC_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "sdhc-ddr","cpu-sdhc"; + operating-points-v2 = <&sdhc2_opp_table>; + + status = "disabled"; + + sdhc2_opp_table: opp-table-2 { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; From 285515eee1c61589f5c4cbcef2bff28e3c5f4da8 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Wed, 8 Apr 2026 19:20:05 +0530 Subject: [PATCH 0827/1058] arm64: dts: qcom: Add USB changes for Shikra Add usb related changes on Shikra specifically: a) Primary controller node b) Primary high speed phy c) QMP Phy for super speed operation Enable USB controller and phys in device mode on CQS and CQM variants. Add the regulators for the phys accordingly. Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 21 +++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 21 +++ arch/arm64/boot/dts/qcom/shikra.dtsi | 142 ++++++++++++++++++++ 3 files changed, 184 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 2b7e2f236c465..d65110aa6b93e 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -60,3 +60,24 @@ &uart0 { status = "okay"; }; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdd-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; + vdda-pll-supply = <&pm4125_l13>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 3022ab4ccffeb..8552841508e9c 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -60,3 +60,24 @@ &uart0 { status = "okay"; }; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdd-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; + vdda-pll-supply = <&pm4125_l13>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 83ebb433bb223..097504814695d 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -488,6 +488,70 @@ #power-domain-cells = <1>; }; + usb_1_hsphy: phy@1613000 { + compatible = "qcom,shikra-qusb2-phy"; + reg = <0x0 0x01613000 0x0 0x180>; + + clocks = <&gcc GCC_AHB2PHY_USB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "cfg_ahb", "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + nvmem-cells = <&qusb2_hstx_trim_1>; + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_qmpphy: phy@1615000 { + compatible = "qcom,shikra-qmp-usb3-phy"; + reg = <0x0 0x01615000 0x0 0x1000>; + + clocks = <&gcc GCC_AHB2PHY_USB_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "cfg_ahb", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_SP0_BCR>, + <&gcc GCC_USB3PHY_PHY_PRIM_SP0_BCR>; + reset-names = "phy", + "phy_phy"; + + #clock-cells = <0>; + clock-output-names = "usb3_phy_pipe_clk_src"; + + #phy-cells = <0>; + orientation-switch; + + qcom,tcsr-reg = <&tcsr_regs 0xb244>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_1_dwc3_ss>; + }; + }; + }; + }; + system_noc: interconnect@1880000 { compatible = "qcom,shikra-sys-noc"; reg = <0x0 0x01880000 0x0 0x6a080>; @@ -534,6 +598,11 @@ #address-cells = <1>; #size-cells = <1>; + qusb2_hstx_trim_1: hstx-trim@258 { + reg = <0x25b 0x1>; + bits = <1 4>; + }; + gpu_speed_bin: gpu-speed-bin@6006 { reg = <0x6006 0x2>; bits = <5 8>; @@ -689,6 +758,79 @@ }; }; + usb_1: usb@4e00000 { + compatible = "qcom,shikra-dwc3", "qcom,snps-dwc3"; + reg = <0x0 0x04e00000 0x0 0xfc100>; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_EN>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <133333333>; + + interrupts-extended = <&intc GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "qusb2_phy", + "ss_phy_irq"; + + iommus = <&apps_smmu 0x120 0x0>; + + phys = <&usb_1_hsphy>, <&usb_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; + + power-domains = <&gcc GCC_USB30_PRIM_GDSC>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; + snps,usb3_lpm_capable; + snps,parkmode-disable-ss-quirk; + + usb-role-switch; + + wakeup-source; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_1_dwc3_ss: endpoint { + remote-endpoint = <&usb_qmpphy_usb_ss_in>; + }; + }; + }; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; From 2955ba5446a0d974ca9faf12b80dc053caf2afc8 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 10 Apr 2026 11:39:45 +0530 Subject: [PATCH 0828/1058] arm64: dts: qcom: shikra: Add cpufreq scaling node Add cpufreq-hw node to support cpufreq scaling on Qualcomm Shikra SoCs. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 097504814695d..b91ea97815757 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -43,6 +43,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + qcom,freq-domain = <&cpufreq_hw 0>; }; cpu1: cpu@100 { @@ -53,6 +54,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + qcom,freq-domain = <&cpufreq_hw 0>; }; cpu2: cpu@200 { @@ -63,6 +65,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + qcom,freq-domain = <&cpufreq_hw 0>; }; cpu3: cpu@300 { @@ -73,6 +76,7 @@ next-level-cache = <&l2_3>; capacity-dmips-mhz = <1946>; dynamic-power-coefficient = <486>; + qcom,freq-domain = <&cpufreq_hw 1>; l2_3: l2-cache { compatible = "cache"; @@ -1062,6 +1066,24 @@ status = "disabled"; }; }; + + cpufreq_hw: cpufreq@fd91000 { + compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; + reg = <0x0 0x0fd91000 0x0 0x1000>, + <0x0 0x0fd92000 0x0 0x1000>; + reg-names = "freq-domain0", + "freq-domain1"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + interrupts = , + ; + interrupt-names = "dcvsh-irq-0", + "dcvsh-irq-1"; + + #freq-domain-cells = <1>; + }; }; timer { From 19b21fefd640b406609ca218be1a7d1eec6de959 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 7 Apr 2026 15:44:34 +0530 Subject: [PATCH 0829/1058] arm64: dts: qcom: shikra: Add SMP2P nodes Add SMP2P nodes for the cdsp, modem and lmcu subsystems to enable inter-processor signalling for remoteproc state management. Signed-off-by: Vishnu Santhosh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index b91ea97815757..4cb2eda53ecd3 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -329,6 +329,75 @@ }; }; + smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + + interrupts = ; + + mboxes = <&apcs_glb 6>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-lmcu { + compatible = "qcom,smp2p"; + qcom,smem = <617>, <616>; + + interrupts = ; + + mboxes = <&apcs_glb 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <26>; + + lmcu_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + lmcu_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-mpss { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupts = ; + + mboxes = <&apcs_glb 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; From 705d263b5fe145367ad18e5ab037abed11fc6362 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 16 Apr 2026 20:03:01 +0530 Subject: [PATCH 0830/1058] arm64: dts: qcom: Enable primary usb controller on IQS platform Enable primary usb controller on IQS platform in peripheral mode. Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 60951524844b2..ef64908d41986 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -60,3 +60,24 @@ &uart0 { status = "okay"; }; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdd-supply = <&pm8150_l4>; + vdda-pll-supply = <&pm8150_l12>; + vdda-phy-dpdm-supply = <&pm8150_l13>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm8150_l6>; + vdda-pll-supply = <&pm8150_l12>; + + status = "okay"; +}; From 0d400b6d6fb3e04a013385381d4fcefb4e175028 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Fri, 10 Apr 2026 17:26:00 +0530 Subject: [PATCH 0831/1058] arm64: dts: qcom: shikra: Enable TSENS and thermal zones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shikra includes one TSENS instance, with a total of 14 thermal sensors distributed across various locations on the SoC. The TSENS max/reset threshold is configured to 120°C in the hardware. Enable all TSENS instances, and define the thermal zones with a hot trip at 110°C and critical trip at 115°C. Signed-off-by: Gaurav Kohli --- arch/arm64/boot/dts/qcom/shikra.dtsi | 267 +++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 4cb2eda53ecd3..2d4e89c148c8b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { interrupt-parent = <&intc>; @@ -704,6 +705,18 @@ qcom,ee = <0>; }; + tsens0: thermal-sensor@4411000 { + compatible = "qcom,shikra-tsens", "qcom,tsens-v2"; + reg = <0x0 0x04411000 0x0 0x1000>, + <0x0 0x04410000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <14>; + #thermal-sensor-cells = <1>; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; @@ -1155,6 +1168,260 @@ }; }; + thermal_zones: thermal-zones { + aoss0-thermal { + thermal-sensors = <&tsens0 0>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + aoss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-0-thermal { + thermal-sensors = <&tsens0 1>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu00-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-1-thermal { + thermal-sensors = <&tsens0 2>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu01-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-0-thermal { + thermal-sensors = <&tsens0 3>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu10-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-1-thermal { + thermal-sensors = <&tsens0 4>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu11-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpuss0-thermal { + thermal-sensors = <&tsens0 5>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpuss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpuss-thermal { + thermal-sensors = <&tsens0 6>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpuss-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nsp-thermal { + thermal-sensors = <&tsens0 7>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + nsp-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss0-thermal { + thermal-sensors = <&tsens0 8>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss1-thermal { + thermal-sensors = <&tsens0 9>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss1-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + camera-thermal { + thermal-sensors = <&tsens0 10>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + camera-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + video-thermal { + thermal-sensors = <&tsens0 11>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + video-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-2-thermal { + thermal-sensors = <&tsens0 12>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu02-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpuss1-thermal { + thermal-sensors = <&tsens0 13>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpuss1-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; + timer { compatible = "arm,armv8-timer"; From 769cd411bd0907a079ef6dbba85c13538cfe518b Mon Sep 17 00:00:00 2001 From: Xueyao An Date: Fri, 17 Apr 2026 16:24:54 +0800 Subject: [PATCH 0832/1058] arm64: dts: qcom: shikra: Add firmware-name to QUPv3 nodes Traditionally, firmware loading for Serial Engines (SE) in the QUP hardware of Qualcomm SoCs has been managed by TrustZone (TZ). While this approach ensures secure SE assignment and access control, it limits flexibility for developers who need to enable various protocols on different SEs. Add the firmware-name property to QUPv3 nodes in the device tree to enable firmware loading from the Linux environment. Handle SE assignments and access control permissions directly within Linux, removing the dependency on TrustZone. Signed-off-by: Xueyao An --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index cf7460e1125d6..10a57da6bc2f3 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -12,3 +12,8 @@ * Sensor DC * NFC DC */ + +&qupv3_0 { + firmware-name = "qcom/shikra/qupv3fw.elf"; + status = "okay"; +}; From b8606a5eb07d69543c0d5d4e2bf3d0d2c331e67b Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 6 Apr 2026 18:27:05 +0530 Subject: [PATCH 0833/1058] arm64: dts: qcom: shikra: Add PMIC thermal and ADC support Add PMIC topic overlay changes for Shikra SOM variants (CQM, CQS, IQS): - Add pm4125 temp-alarm and VADC channel nodes - Add pm8005 temp-alarm node - Add thermal zones for PMIC and system thermistors - Add GPIO key (volume up) bindings - Add ADC thermal bridge nodes for pa/quiet/msm thermistors - Disable pm8005 regulators across SOM variants - Switch SPMI interrupt to MPM edge-triggered Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/pm4125.dtsi | 77 +++++++ arch/arm64/boot/dts/qcom/pm8005.dtsi | 7 + arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 223 ++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 224 +++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 158 +++++++++++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 6 files changed, 690 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/pm4125.dtsi b/arch/arm64/boot/dts/qcom/pm4125.dtsi index 542e8fe030da4..7113504d5941a 100644 --- a/arch/arm64/boot/dts/qcom/pm4125.dtsi +++ b/arch/arm64/boot/dts/qcom/pm4125.dtsi @@ -65,6 +65,83 @@ status = "disabled"; }; + pm4125_tz: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + io-channels = <&pm4125_adc ADC5_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + status = "disabled"; + }; + + pm4125_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + + /* Channel nodes */ + channel@0 { + reg = ; + label = "ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@1 { + reg = ; + label = "vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@6 { + reg = ; + label = "die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@7 { + reg = ; + label = "usb_in_i_uv"; + qcom,pre-scaling = <1 1>; + }; + + channel@8 { + reg = ; + label = "usb_in_v_div_16"; + qcom,pre-scaling = <1 16>; + }; + + channel@9 { + reg = ; + label = "chg_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@4b { + reg = ; + label = "bat_id"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@83 { + reg = ; + label = "vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + + channel@84 { + reg = ; + label = "vbat_sns"; + qcom,pre-scaling = <1 3>; + }; + }; + rtc@6000 { compatible = "qcom,pm8941-rtc"; reg = <0x6000>, <0x6100>; diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi index 0f0ab2da83055..2867ace2fa1ce 100644 --- a/arch/arm64/boot/dts/qcom/pm8005.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8005.dtsi @@ -11,6 +11,13 @@ #address-cells = <1>; #size-cells = <0>; + pm8005_tz: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x4 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + #thermal-sensor-cells = <0>; + }; + pm8005_gpios: gpio@c000 { compatible = "qcom,pm8005-gpio", "qcom,spmi-gpio"; reg = <0xc000>; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 79ea476c7c4a6..42f0b29330dcc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -3,9 +3,136 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include +#include +#include +#include + #include "shikra.dtsi" +#include "pm4125.dtsi" +#include "pm8005.dtsi" /* Modem, Cocos + Kunlun PMIC */ +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm4125_gpios 9 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; + + pm4125_msm_therm_bridge: pm4125-msm-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_pa_therm_bridge: pm4125-pa-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM1_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_quiet_therm_bridge: pm4125-quiet-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM2_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; +}; + +&pm4125_adc { + pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; + pinctrl-names = "default"; + status = "okay"; + + channel@4d { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4f { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@54 { + reg = ; + label = "chgr_skin"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm4125_gpios { + pm4125_adc_gpio5_default: pm4125-adc-gpio5-state { + pins = "gpio5"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm4125_adc_gpio6_default: pm4125-adc-gpio6-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio9"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&pm4125_resin { + linux,code = ; + status = "okay"; +}; + +&pm4125_tz { + status = "okay"; +}; + +&pm8005_regulators { + status = "disabled"; +}; &rpm_requests { regulators { @@ -137,3 +264,99 @@ }; }; }; + +&thermal_zones { + pm4125-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm4125_tz>; + + trips { + pm4125_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm4125_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "hot"; + }; + + pm4125_trip2: trip2 { + temperature = <155000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + pm8005-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm8005_tz>; + + trips { + pm8005_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip2: trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_pa_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_quiet_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_msm_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index 2434c997173e2..14100f35c9383 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -3,10 +3,138 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include +#include +#include +#include + #include "shikra.dtsi" +#include "pm4125.dtsi" +#include "pm8005.dtsi" /* APQ (No Modem), Cocos + Kunlun PMIC */ +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm4125_gpios 9 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; + + pm4125_msm_therm_bridge: pm4125-msm-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_pa_therm_bridge: pm4125-pa-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM1_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_quiet_therm_bridge: pm4125-quiet-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM2_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; +}; + +&pm4125_adc { + pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; + pinctrl-names = "default"; + status = "okay"; + + channel@4d { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4f { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@54 { + reg = ; + label = "chgr_skin"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm4125_gpios { + pm4125_adc_gpio5_default: pm4125-adc-gpio5-state { + pins = "gpio5"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm4125_adc_gpio6_default: pm4125-adc-gpio6-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio9"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&pm4125_resin { + linux,code = ; + status = "okay"; +}; + +&pm4125_tz { + status = "okay"; +}; + +&pm8005_regulators { + status = "disabled"; +}; + &rpm_requests { regulators { compatible = "qcom,rpm-pm2250-regulators"; @@ -137,3 +265,99 @@ }; }; }; + +&thermal_zones { + pm4125-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm4125_tz>; + + trips { + pm4125_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm4125_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "hot"; + }; + + pm4125_trip2: trip2 { + temperature = <155000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + pm8005-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm8005_tz>; + + trips { + pm8005_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip2: trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_pa_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_quiet_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_msm_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index 9581f98b7d08e..88b1472cf87cc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -3,9 +3,129 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include +#include +#include +#include + #include "shikra.dtsi" +#include "pm8150.dtsi" /* APQ (No Modem), Wailua PMIC */ + +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm8150_gpios 6 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; +}; + +&pm8150_adc { + pinctrl-0 = <&pm8150_adc_gpio2_default>, <&pm8150_adc_gpio3_default>; + pinctrl-names = "default"; + + channel@4d { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@52 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm8150_adc_tm { + status = "okay"; + + pa-therm@0 { + reg = <0>; + io-channels = <&pm8150_adc ADC5_GPIO4_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; + + quiet-therm@1 { + reg = <1>; + io-channels = <&pm8150_adc ADC5_AMUX_THM2_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; + + msm-therm@2 { + reg = <2>; + io-channels = <&pm8150_adc ADC5_AMUX_THM1_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; +}; + +&pm8150_gpios { + pm8150_adc_gpio2_default: pm8150-adc-gpio2-state { + pins = "gpio2"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm8150_adc_gpio3_default: pm8150-adc-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; + +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + status = "okay"; +}; + &rpm_requests { regulators { compatible = "qcom,rpm-pm8150-regulators"; @@ -126,3 +246,41 @@ }; }; }; + +&thermal_zones { + sys-1-thermal { + thermal-sensors = <&pm8150_adc_tm 0>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + thermal-sensors = <&pm8150_adc_tm 1>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + thermal-sensors = <&pm8150_adc_tm 2>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 2d4e89c148c8b..79cc8d65ca271 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -695,7 +695,7 @@ "obsrvr", "intr", "cnfg"; - interrupts-extended = <&mpm 86 IRQ_TYPE_LEVEL_HIGH>; + interrupts-extended = <&mpm 86 IRQ_TYPE_EDGE_RISING>; interrupt-names = "periph_irq"; interrupt-controller; #interrupt-cells = <4>; From 52c2aece4c18c47f7cb327cada6014a8f8830ce1 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 16 Apr 2026 23:09:19 +0530 Subject: [PATCH 0834/1058] arm64: dts: qcom: Add DISPCC and GPUCC nodes support Add support for DISPCC and GPUCC nodes on Qualcomm Shikra platforms. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 79cc8d65ca271..f17ccb845f427 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -4,7 +4,9 @@ */ #include +#include #include +#include #include #include #include @@ -917,6 +919,17 @@ }; }; + gpucc: clock-controller@5990000 { + compatible = "qcom,shikra-gpucc"; + reg = <0x0 0x05990000 0x0 0x9000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + adreno_smmu: iommu@59a0000 { compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; @@ -934,6 +947,21 @@ ; }; + dispcc: clock-controller@5f00000 { + compatible = "qcom,shikra-dispcc"; + reg = <0x0 0x05f00000 0x0 0x20000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, + <0>, + <0>, + <0>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + sram@c11e000 { compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; reg = <0x0 0x0c11e000 0x0 0x1000>; From d1dc0e9c62c80714ebbd91dffe84bdc5d0130c22 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Wed, 15 Apr 2026 18:41:44 +0530 Subject: [PATCH 0835/1058] arm64: dts: qcom: Add clock nodes for adreno smmu Add clock entries for adreno smmu node in Shikra. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index f17ccb845f427..992fa6272084b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -945,6 +945,17 @@ , , ; + + clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>; + clock-names = "hlos", + "mem", + "iface", + "ahb"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>; }; dispcc: clock-controller@5f00000 { From b8b80ebf6c15cf16f860f4a5f52fa500b891f62b Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Thu, 16 Apr 2026 15:18:05 +0800 Subject: [PATCH 0836/1058] arm64: dts: qcom: shikra: add WiFi node support Introduce the WiFi hardware description in shikra.dtsi, including register space, interrupts, IOMMU configuration and reserved memory. The node is kept disabled by default and is intended to be enabled by board-specific device trees. Signed-off-by: Miaoqing Pan --- arch/arm64/boot/dts/qcom/shikra.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 992fa6272084b..9b765351137e0 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1061,6 +1061,29 @@ ; }; + wifi: wifi@c800000 { + compatible = "qcom,wcn3990-wifi"; + reg = <0x0 0x0c800000 0x0 0x800000>; + reg-names = "membase"; + memory-region = <&wlan_mem>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + iommus = <&apps_smmu 0x1a0 0x1>; + qcom,msa-fixed-perm; + + status = "disabled"; + }; + intc: interrupt-controller@f200000 { compatible = "arm,gic-v3"; reg = <0x0 0xf200000 0x0 0x10000>, /* GICD */ From f3d53cad47b1048d5a1deacbdc677fd4f7088e00 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 20 Apr 2026 10:11:12 +0800 Subject: [PATCH 0837/1058] arm64: dts: qcom: shikra: enable WiFi on EVK boards Enable WiFi support on Shikra CQS, CQM and IQS EVK variants. Provide board-specific WiFi configuration, including power supply connections and calibration variant selection. The WiFi node is enabled on each EVK according to the corresponding PMIC and board design. Signed-off-by: Miaoqing Pan --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 11 +++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 11 +++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 21 +++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index d65110aa6b93e..6cb829f25e0f9 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -81,3 +81,14 @@ status = "okay"; }; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&pm4125_l13>; + vdd-1.3-rfa-supply = <&pm4125_l10>; + vdd-3.3-ch0-supply = <&pm4125_l22>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "cq2390"; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 8552841508e9c..1d207eb5607b7 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -81,3 +81,14 @@ status = "okay"; }; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&pm4125_l13>; + vdd-1.3-rfa-supply = <&pm4125_l10>; + vdd-3.3-ch0-supply = <&pm4125_l22>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "cq2390"; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index ef64908d41986..5ccdea654d16c 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -23,6 +23,16 @@ chosen { stdout-path = "serial0:115200n8"; }; + + regulators { + vreg_wlan_3p3_dummy: regulator-wlan-3p3-dummy { + compatible = "regulator-fixed"; + regulator-name = "wlan_3p3_dummy"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; }; &sdhc_1 { @@ -81,3 +91,14 @@ status = "okay"; }; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm8150_s4>; + vdd-1.8-xo-supply = <&pm8150_l12>; + vdd-1.3-rfa-supply = <&pm8150_l8>; + vdd-3.3-ch0-supply = <&vreg_wlan_3p3_dummy>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "cq2390"; + + status = "okay"; +}; From 73f3e62a00215d736579b532577d960dd72dd13c Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 20 Apr 2026 19:32:46 +0530 Subject: [PATCH 0838/1058] arm64: dts: qcom: shikra: Add Iris video codec node Add the Iris video codec device tree node for the Shikra platform. Shikra reuses the QCM2290-class video hardware and programming model. The video node is added to describe the Iris based video decoder encoder block, allowing the media driver to probe and initialize the hardware. Signed-off-by: Dikshita Agarwal --- arch/arm64/boot/dts/qcom/shikra.dtsi | 61 ++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 9b765351137e0..73d7f0c5b5df3 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -958,6 +958,67 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; }; + iris: video-codec@5a00000 { + compatible = "qcom,shikra-iris", "qcom,qcm2290-venus"; + reg = <0 0x5a00000 0 0x200000>; + interrupts = ; + + power-domains = <&gcc GCC_VENUS_GDSC>, + <&gcc GCC_VCODEC0_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "venus", + "vcodec0", + "cx"; + operating-points-v2 = <&venus_opp_table>; + + clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>, + <&gcc GCC_VENUS_CTL_AXI_CLK>, + <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>, + <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>, + <&gcc GCC_VCODEC0_AXI_CLK>; + clock-names = "core", + "iface", + "bus", + "throttle", + "vcodec0_core", + "vcodec0_bus"; + + memory-region = <&video_mem>; + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_VENUS_CFG RPM_ALWAYS_TAG>; + interconnect-names = "video-mem", + "cpu-cfg"; + + iommus = <&apps_smmu 0x780 0x0020>; + + venus_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133333333 { + opp-hz = /bits/ 64 <133333333>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + dispcc: clock-controller@5f00000 { compatible = "qcom,shikra-dispcc"; reg = <0x0 0x05f00000 0x0 0x20000>; From 480b7a93e5ad7bf6f5d22d553fbc39f19af6ee56 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 20 Apr 2026 19:33:38 +0530 Subject: [PATCH 0839/1058] arm64: dts: qcom: shikra-evk: Enable Iris core Enable video en/decoder on the Shikra EVK board. Signed-off-by: Dikshita Agarwal --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 10a57da6bc2f3..e69499f77c682 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -13,6 +13,10 @@ * NFC DC */ +&iris { + status = "okay"; +}; + &qupv3_0 { firmware-name = "qcom/shikra/qupv3fw.elf"; status = "okay"; From fc9e5454582ac40673354514c9bb783db216a84c Mon Sep 17 00:00:00 2001 From: Xueyao An Date: Thu, 16 Apr 2026 12:34:14 +0800 Subject: [PATCH 0840/1058] arm64: dts: qcom: Add QUPv3 configuration for Shikra Add device tree support for QUPv3 serial engine protocols on Shikra. Shikra has 10 QUP serial engines under a single QUP wrapper, all with support of GPI DMA engines. Signed-off-by: Xueyao An --- arch/arm64/boot/dts/qcom/shikra.dtsi | 951 +++++++++++++++++++++++++++ 1 file changed, 951 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 73d7f0c5b5df3..01cb29a4c24c7 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -435,6 +436,161 @@ gpio-ranges = <&tlmm 0 0 165>; wakeup-parent = <&mpm>; + qup_i2c0_data_clk: qup-i2c0-data-clk-state { + /* SDA, SCL */ + pins = "gpio2", "gpio3"; + function = "qup0_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c1_data_clk: qup-i2c1-data-clk-state { + /* SDA, SCL */ + pins = "gpio4", "gpio5"; + function = "qup0_se1_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c2_data_clk: qup-i2c2-data-clk-state { + /* SDA, SCL */ + pins = "gpio6", "gpio7"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c3_data_clk: qup-i2c3-data-clk-state { + /* SDA, SCL */ + pins = "gpio10", "gpio11"; + function = "qup0_se3_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c4_data_clk: qup-i2c4-data-clk-state { + /* SDA, SCL */ + pins = "gpio12", "gpio13"; + function = "qup0_se4_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c5_data_clk: qup-i2c5-data-clk-state { + /* SDA, SCL */ + pins = "gpio14", "gpio15"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c6_data_clk: qup-i2c6-data-clk-state { + /* SDA, SCL */ + pins = "gpio18", "gpio19"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c7_data_clk: qup-i2c7-data-clk-state { + /* SDA, SCL */ + pins = "gpio20", "gpio21"; + function = "qup0_se7_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c8_data_clk: qup-i2c8-data-clk-state { + /* SDA, SCL */ + pins = "gpio22", "gpio23"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c9_data_clk: qup-i2c9-data-clk-state { + /* SDA, SCL */ + pins = "gpio27", "gpio26"; + function = "qup0_se9_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi0_cs: qup-spi0-cs-state { + pins = "gpio1"; + function = "qup0_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi0_data_clk: qup-spi0-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio2", "gpio3", "gpio0"; + function = "qup0_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi2_cs: qup-spi2-cs-state { + pins = "gpio9"; + function = "qup0_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi2_data_clk: qup-spi2-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio6", "gpio7", "gpio8"; + function = "qup0_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi5_cs: qup-spi5-cs-state { + pins = "gpio17"; + function = "qup0_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi5_data_clk: qup-spi5-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio14", "gpio15", "gpio16"; + function = "qup0_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi6_cs: qup-spi6-cs-state { + pins = "gpio29"; + function = "qup0_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi6_data_clk: qup-spi6-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio18", "gpio19", "gpio28"; + function = "qup0_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi8_cs: qup-spi8-cs-state { + pins = "gpio25"; + function = "qup0_se8"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi8_data_clk: qup-spi8-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio22", "gpio23", "gpio24"; + function = "qup0_se8"; + drive-strength = <6>; + bias-disable; + }; + qup_uart0_default: qup-uart0-default-state { pins = "gpio0", "gpio1"; function = "qup0_se0"; @@ -442,6 +598,105 @@ bias-disable; }; + qup_uart1_default: qup-uart1-default-state { + pins = "gpio4", "gpio5"; + function = "qup0_se1_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart2_default: qup-uart2-default-state { + /* TX, RX */ + pins = "gpio8", "gpio9"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart2_cts_rts: qup-uart2-cts-rts-state { + /* CTS, RTS */ + pins = "gpio6", "gpio7"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart3_default: qup-uart3-default-state { + pins = "gpio10", "gpio11"; + function = "qup0_se3_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart4_default: qup-uart4-default-state { + pins = "gpio12", "gpio13"; + function = "qup0_se4_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart5_default: qup-uart5-default-state { + /* TX, RX */ + pins = "gpio16", "gpio17"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart5_cts_rts: qup-uart5-cts-rts-state { + /* CTS, RTS */ + pins = "gpio14", "gpio15"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart6_default: qup-uart6-default-state { + /* TX, RX */ + pins = "gpio28", "gpio29"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart6_cts_rts: qup-uart6-cts-rts-state { + /* CTS, RTS */ + pins = "gpio18", "gpio19"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart7_default: qup-uart7-default-state { + pins = "gpio20", "gpio21"; + function = "qup0_se7_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart8_default: qup-uart8-default-state { + /* TX, RX */ + pins = "gpio24", "gpio25"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart8_cts_rts: qup-uart8-cts-rts-state { + /* CTS, RTS */ + pins = "gpio22", "gpio23"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart9_default: qup-uart9-default-state { + pins = "gpio26", "gpio27"; + function = "qup0_se9_23"; + drive-strength = <2>; + bias-disable; + }; + sdc1_state_on: sdc1-on-state { clk-pins { pins = "sdc1_clk"; @@ -1236,6 +1491,34 @@ }; }; + gpi_dma0: dma-controller@4a00000 { + compatible = "qcom,shikra-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x04a00000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <16>; + dma-channel-mask = <0xff>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0xf6 0x0>; + }; + qupv3_0: geniqup@4ac0000 { compatible = "qcom,geni-se-qup"; reg = <0x0 0x04ac0000 0x0 0x2000>; @@ -1245,10 +1528,75 @@ clock-names = "m-ahb", "s-ahb"; + iommus = <&apps_smmu 0xe3 0x0>; + #address-cells = <2>; #size-cells = <2>; ranges; + status = "disabled"; + + i2c0: i2c@4a80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>, + <&gpi_dma0 1 0 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c0_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi0: spi@4a80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>, + <&gpi_dma0 1 0 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi0_data_clk>, <&qup_spi0_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + uart0: serial@4a80000 { compatible = "qcom,geni-debug-uart"; reg = <0x0 0x04a80000 0x0 0x4000>; @@ -1270,6 +1618,609 @@ status = "disabled"; }; + + i2c1: i2c@4a84000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>, + <&gpi_dma0 1 1 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c1_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart1: serial@4a84000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart1_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c2: i2c@4a88000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + pinctrl-0 = <&qup_i2c2_data_clk>; + pinctrl-names = "default"; + + dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>, + <&gpi_dma0 1 2 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi2: spi@4a88000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>, + <&gpi_dma0 1 2 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi2_data_clk>, <&qup_spi2_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart2: serial@4a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a88000 0x0 0x4000>; + + interrupts-extended = <&intc GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 9 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart2_default>, <&qup_uart2_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c3: i2c@4a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>, + <&gpi_dma0 1 3 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c3_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart3: serial@4a8c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart3_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c4: i2c@4a90000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>, + <&gpi_dma0 1 4 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c4_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart4: serial@4a90000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart4_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c5: i2c@4a94000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>, + <&gpi_dma0 1 5 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c5_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi5: spi@4a94000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>, + <&gpi_dma0 1 5 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi5_data_clk>, <&qup_spi5_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart5: serial@4a94000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart5_default>, <&qup_uart5_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c6: i2c@4a98000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>, + <&gpi_dma0 1 6 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c6_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi6: spi@4a98000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 6 QCOM_GPI_SPI>, + <&gpi_dma0 1 6 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi6_data_clk>, <&qup_spi6_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart6: serial@4a98000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart6_default>, <&qup_uart6_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c7: i2c@4a9c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>, + <&gpi_dma0 1 7 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c7_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart7: serial@4a9c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart7_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c8: i2c@4aa0000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 8 QCOM_GPI_I2C>, + <&gpi_dma0 1 8 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c8_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi8: spi@4aa0000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 8 QCOM_GPI_SPI>, + <&gpi_dma0 1 8 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi8_data_clk>, <&qup_spi8_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart8: serial@4aa0000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart8_default>, <&qup_uart8_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c9: i2c@4aa4000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4aa4000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 9 QCOM_GPI_I2C>, + <&gpi_dma0 1 9 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c9_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart9: serial@4aa4000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04aa4000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart9_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; }; cpufreq_hw: cpufreq@fd91000 { From 80cba24c917c49de8329a6c0b4b3c6f97ca6063a Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 20 Apr 2026 18:16:57 +0530 Subject: [PATCH 0841/1058] arm64: dts: qcom: shikra: enable USB-C port handling Enable USB role switching and USB-C orientation handling for the Qualcomm shikra board. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 18 +++++++++- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 38 ++++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 18 +++++++++- arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 38 ++++++++++++++++++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 6cb829f25e0f9..63128d33cc973 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -25,6 +25,14 @@ }; }; +&pm4125_hs_in { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&pm4125_ss_in { + remote-endpoint = <&usb_qmpphy_out>; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -62,11 +70,15 @@ }; &usb_1 { - dr_mode = "peripheral"; + dr_mode = "otg"; status = "okay"; }; +&usb_1_dwc3_hs { + remote-endpoint = <&pm4125_hs_in>; +}; + &usb_1_hsphy { vdd-supply = <&pm4125_l12>; vdda-pll-supply = <&pm4125_l13>; @@ -92,3 +104,7 @@ status = "okay"; }; + +&usb_qmpphy_out { + remote-endpoint = <&pm4125_ss_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 42f0b29330dcc..26cf4b0f31a48 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -126,10 +126,48 @@ status = "okay"; }; +&pm4125_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pm4125_hs_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + pm4125_ss_in: endpoint { + }; + }; + }; + }; +}; + &pm4125_tz { status = "okay"; }; +&pm4125_vbus { + regulator-min-microamp = <500000>; + regulator-max-microamp = <500000>; + status = "okay"; +}; + &pm8005_regulators { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 1d207eb5607b7..c6d5337d9bf15 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -25,6 +25,14 @@ }; }; +&pm4125_hs_in { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&pm4125_ss_in { + remote-endpoint = <&usb_qmpphy_out>; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -62,11 +70,15 @@ }; &usb_1 { - dr_mode = "peripheral"; + dr_mode = "otg"; status = "okay"; }; +&usb_1_dwc3_hs { + remote-endpoint = <&pm4125_hs_in>; +}; + &usb_1_hsphy { vdd-supply = <&pm4125_l12>; vdda-pll-supply = <&pm4125_l13>; @@ -92,3 +104,7 @@ status = "okay"; }; + +&usb_qmpphy_out { + remote-endpoint = <&pm4125_ss_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index 14100f35c9383..e9f5469768010 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -127,10 +127,48 @@ status = "okay"; }; +&pm4125_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pm4125_hs_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + pm4125_ss_in: endpoint { + }; + }; + }; + }; +}; + &pm4125_tz { status = "okay"; }; +&pm4125_vbus { + regulator-min-microamp = <500000>; + regulator-max-microamp = <500000>; + status = "okay"; +}; + &pm8005_regulators { status = "disabled"; }; From 8cd13ecfe0873b23539876f54fb806535eac4119 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Wed, 22 Apr 2026 17:01:38 +0530 Subject: [PATCH 0842/1058] arm64: dts: qcom: shikra: correct RPM tags for iris interconnects Flip RPMh tags so CPU configuration paths use RPM_ACTIVE_TAG and video memory paths use RPM_ALWAYS_TAG, matching intended power management behavior. Signed-off-by: Dikshita Agarwal --- arch/arm64/boot/dts/qcom/shikra.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 01cb29a4c24c7..558f18825a5aa 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1240,10 +1240,10 @@ "vcodec0_bus"; memory-region = <&video_mem>; - interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ACTIVE_TAG - &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, - <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG - &config_noc SLAVE_VENUS_CFG RPM_ALWAYS_TAG>; + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>; interconnect-names = "video-mem", "cpu-cfg"; From 50241f29479c190eefedcc3b2fdccb8518e8aa42 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 24 Apr 2026 16:38:09 +0530 Subject: [PATCH 0843/1058] arm64: dts: qcom: shikra: Add LLCC node Add a DT node for the Last Level Cache Controller (LLCC) on the Shikra SoC. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 558f18825a5aa..d4a1c0775a563 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -803,6 +803,15 @@ #interconnect-cells = <2>; }; + llcc: system-cache-controller@e00000 { + compatible = "qcom,shikra-llcc"; + reg = <0x0 0x00e00000 0x0 0x80000>, + <0x0 0x0f00000 0x0 0x80000>, + <0x0 0x1000000 0x0 0x80000>; + reg-names = "llcc0_base", "llcc1_base", "llcc_broadcast_base"; + interrupts = ; + }; + gcc: clock-controller@1400000 { compatible = "qcom,shikra-gcc"; reg = <0x0 0x01400000 0x0 0x1f0000>; From 6ad344ff3e56140bad58e06c8e087d236c3bfec7 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 20 Apr 2026 14:28:10 +0530 Subject: [PATCH 0844/1058] arm64: dts: qcom: shikra: Add CDSP, LPAICP, MPSS remoteproc PAS nodes Add nodes for remoteproc PAS loader for CDSP, LPAICP, MPSS subsystem. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 169 +++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index d4a1c0775a563..329da699a03d7 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2232,6 +2232,174 @@ }; }; + remoteproc_mpss: remoteproc@6080000 { + compatible = "qcom,shikra-mpss-pas"; + reg = <0x0 0x06080000 0x0 0x100>; + + interrupts-extended = <&intc GIC_SPI 307 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + + power-domains = <&rpmpd RPMHPD_CX>; + + memory-region = <&mpss_wlan_mem>; + + qcom,smem-states = <&modem_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 12>; + qcom,remote-pid = <1>; + label = "mpss"; + }; + }; + + remoteproc_cdsp: remoteproc@b300000 { + compatible = "qcom,shikra-cdsp-pas"; + reg = <0x0 0x0b300000 0x0 0x100000>; + + interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + + power-domains = <&rpmpd RPMHPD_CX>; + + memory-region = <&cdsp_mem>; + + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 4>; + qcom,remote-pid = <5>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,fastrpc"; + #address-cells = <1>; + #size-cells = <0>; + label = "cdsp"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x0201 0x0000>; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x0202 0x0000>; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x0203 0x0000>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x0204 0x0000>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x0205 0x0000>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x0206 0x0000>; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu 0x0209 0x0000>; + }; + }; + }; + }; + + remoteproc_lpaicp: remoteproc@b800000 { + compatible = "qcom,shikra-lpaicp-pas"; + reg = <0x0 0x0b800000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING>, + <&lmcu_smp2p_in 0 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 1 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 2 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 3 IRQ_TYPE_NONE>; + + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + memory-region = <&lmcu_mem &lmcu_dtb_mem>; + + qcom,smem-states = <&lmcu_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 9>; + qcom,remote-pid = <26>; + label = "lpaicp"; + }; + }; + cpufreq_hw: cpufreq@fd91000 { compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; reg = <0x0 0x0fd91000 0x0 0x1000>, @@ -2249,6 +2417,7 @@ #freq-domain-cells = <1>; }; + }; thermal_zones: thermal-zones { From 232f046a529073a11792f80df3452c347d8c6a32 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 30 Apr 2026 17:27:49 +0530 Subject: [PATCH 0845/1058] arm64: dts: qcom: shikra-cqm: Enable CDSP, LPAICP and MPSS Enable CDSP, LPAICP and MPSS for Qualcomm's shikra-cqm board. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 63128d33cc973..e864b995443ef 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -33,6 +33,25 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/shikra/qdsp6sw.mbn"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; From 8289a0c957b1837513b2471f857349c12d3c7cc9 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 30 Apr 2026 17:37:31 +0530 Subject: [PATCH 0846/1058] arm64: dts: qcom: shikra-cqs: Enable CDSP and LPAICP Enable CDSP and LPAICP for Qualcomm's shikra-cqs board. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index c6d5337d9bf15..47f0dfeb6b627 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -33,6 +33,19 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; From c5d9f6c22e9e4f543e9f60e70736d436e96feab5 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 30 Apr 2026 17:38:39 +0530 Subject: [PATCH 0847/1058] arm64: dts: qcom: shikra-iqs: Enable CDSP and LPAICP Enable CDSP and LPAICP for Qualcomm's shikra-iqs board. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 5ccdea654d16c..52862e4e2f57d 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -35,6 +35,19 @@ }; }; +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm8150_l17>; vqmmc-supply = <&pm8150_s4>; From 6db99e4322a0f46277e5fcb44decff8921566e06 Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Thu, 7 May 2026 15:59:40 +0530 Subject: [PATCH 0848/1058] arm64: dts: qcom: shikra: Enable cpufreq cooling devices Add cooling-cells property to the CPU nodes to support cpufreq cooling devices. Signed-off-by: Aastha Pandey --- arch/arm64/boot/dts/qcom/shikra.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 329da699a03d7..cce9ec554b16c 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -48,6 +48,7 @@ capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; }; cpu1: cpu@100 { @@ -59,6 +60,7 @@ capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; }; cpu2: cpu@200 { @@ -70,6 +72,7 @@ capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; }; cpu3: cpu@300 { @@ -81,6 +84,7 @@ capacity-dmips-mhz = <1946>; dynamic-power-coefficient = <486>; qcom,freq-domain = <&cpufreq_hw 1>; + #cooling-cells = <2>; l2_3: l2-cache { compatible = "cache"; From 18b00e7bea6328e63b1a6a2430c836646e42797f Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Sun, 10 May 2026 02:21:51 +0530 Subject: [PATCH 0849/1058] arm64: dts: qcom: shikra: update reserved memory regions Update reserved memory regions for Shikra aligning with new set of no-map regions. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index cce9ec554b16c..dc11e54d868f8 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -265,12 +265,6 @@ no-map; }; - pvm_fw_mem: pvm-fw@86300000 { - reg = <0x0 0x86300000 0x0 0x100000>; - no-map; - }; - - /* UEFI region at 0x9F400000 is reclaimed by Linux */ tz_stat_mem: tz-stat@a0000000 { reg = <0x0 0xa0000000 0x0 0x100000>; no-map; @@ -321,20 +315,6 @@ no-map; }; - /* Linux kernel image is loaded at 0xB5000000 */ - trust_ui_vm_mem: trust-ui-vm@f3800000 { - compatible = "shared-dma-pool"; - reg = <0x0 0xf3800000 0x0 0x4000000>; - alignment = <0x0 0x400000>; - reusable; - }; - - oem_vm_mem: oem-vm@f7c00000 { - compatible = "shared-dma-pool"; - reg = <0x0 0xf7c00000 0x0 0x4c00000>; - alignment = <0x0 0x400000>; - reusable; - }; }; smp2p-cdsp { From 35b38de940f60407970bcd31e829ce88c28d3f86 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Sun, 10 May 2026 02:32:46 +0530 Subject: [PATCH 0850/1058] arm64: dts: qcom: shikra: fix compatible field for iommu nodes Fix compatible entries for apps_smmu and adreno_smmu nodes, add missing "qcom,adreno-smmu" compatible entry for adreno_smmu node. Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/shikra.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index dc11e54d868f8..d6526f1d214af 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1179,7 +1179,8 @@ }; adreno_smmu: iommu@59a0000 { - compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + compatible = "qcom,shikra-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x059a0000 0x0 0x10000>; #iommu-cells = <2>; #global-interrupts = <1>; @@ -1297,8 +1298,7 @@ }; apps_smmu: iommu@c600000 { - compatible = "qcom,shikra-smmu-500", "qcom,adreno-smmu", - "qcom,smmu-500", "arm,mmu-500"; + compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x0c600000 0x0 0x80000>; #iommu-cells = <2>; #global-interrupts = <1>; From 500f0733a99948c8eb3ca97541d7910921c19ee2 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Mon, 11 May 2026 16:19:12 +0530 Subject: [PATCH 0851/1058] arm64: dts: qcom: Modify MPM pin count for shikra Modify MPM pin count to incorporate all MPM interrupts that can be configured. Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index d6526f1d214af..a3b981d552bfe 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -221,7 +221,7 @@ #interrupt-cells = <2>; #power-domain-cells = <0>; interrupt-parent = <&intc>; - qcom,mpm-pin-count = <95>; + qcom,mpm-pin-count = <96>; qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */ <12 422>, /* DWC3 ss_phy_irq */ <58 272>, /* QUSB2_PHY dmse_hv_vddmx */ From 54159d381ff3800cb4d6ecce0e432ac51968204f Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 11 May 2026 15:58:56 +0530 Subject: [PATCH 0852/1058] arm64: dts: qcom: Update Min and max Voltages for Shikra Retail Remove unused regulators (s1, s4, l1, l2, l11) and tighten min/max voltage ranges for remaining rails to match actual operating voltages derived from PGA report analysis. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 73 +++++++------------- arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 73 +++++++------------- 2 files changed, 48 insertions(+), 98 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 26cf4b0f31a48..107dcb442f0d8 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -176,43 +176,23 @@ regulators { compatible = "qcom,rpm-pm2250-regulators"; - pm4125_s1: s1 { - regulator-min-microvolt = <1396000>; - regulator-max-microvolt = <1950000>; - }; - pm4125_s2: s2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1200000>; }; - pm4125_s4: s4 { - regulator-min-microvolt = <640000>; - regulator-max-microvolt = <1414000>; - }; - - pm4125_l1: l1 { - regulator-min-microvolt = <312000>; - regulator-max-microvolt = <1304000>; - }; - - pm4125_l2: l2 { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1200000>; - }; - pm4125_l3: l3 { - regulator-min-microvolt = <570000>; + regulator-min-microvolt = <624000>; regulator-max-microvolt = <650000>; }; pm4125_l4: l4 { - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l5: l5 { - regulator-min-microvolt = <1100000>; + regulator-min-microvolt = <1232000>; regulator-max-microvolt = <1304000>; }; @@ -227,7 +207,7 @@ }; pm4125_l8: l8 { - regulator-min-microvolt = <875000>; + regulator-min-microvolt = <928000>; regulator-max-microvolt = <1000000>; }; @@ -237,68 +217,63 @@ }; pm4125_l10: l10 { - regulator-min-microvolt = <1150000>; + regulator-min-microvolt = <1304000>; regulator-max-microvolt = <1304000>; }; - pm4125_l11: l11 { - regulator-min-microvolt = <970000>; - regulator-max-microvolt = <1150000>; - }; - pm4125_l12: l12 { - regulator-min-microvolt = <875000>; + regulator-min-microvolt = <928000>; regulator-max-microvolt = <975000>; }; pm4125_l13: l13 { regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1950000>; + regulator-max-microvolt = <1800000>; }; pm4125_l14: l14 { - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <1950000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; pm4125_l15: l15 { regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2000000>; + regulator-max-microvolt = <1800000>; }; pm4125_l16: l16 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <2000000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; pm4125_l17: l17 { - regulator-min-microvolt = <2900000>; + regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3544000>; }; pm4125_l18: l18 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l19: l19 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l20: l20 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3544000>; + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <2952000>; }; pm4125_l21: l21 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3544000>; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3056000>; }; pm4125_l22: l22 { - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; + regulator-min-microvolt = <3304000>; + regulator-max-microvolt = <3304000>; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index e9f5469768010..8094df7e607e1 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -177,43 +177,23 @@ regulators { compatible = "qcom,rpm-pm2250-regulators"; - pm4125_s1: s1 { - regulator-min-microvolt = <1396000>; - regulator-max-microvolt = <1950000>; - }; - pm4125_s2: s2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1200000>; }; - pm4125_s4: s4 { - regulator-min-microvolt = <640000>; - regulator-max-microvolt = <1414000>; - }; - - pm4125_l1: l1 { - regulator-min-microvolt = <312000>; - regulator-max-microvolt = <1304000>; - }; - - pm4125_l2: l2 { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1200000>; - }; - pm4125_l3: l3 { - regulator-min-microvolt = <570000>; + regulator-min-microvolt = <624000>; regulator-max-microvolt = <650000>; }; pm4125_l4: l4 { - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l5: l5 { - regulator-min-microvolt = <1100000>; + regulator-min-microvolt = <1232000>; regulator-max-microvolt = <1304000>; }; @@ -228,7 +208,7 @@ }; pm4125_l8: l8 { - regulator-min-microvolt = <875000>; + regulator-min-microvolt = <928000>; regulator-max-microvolt = <1000000>; }; @@ -238,68 +218,63 @@ }; pm4125_l10: l10 { - regulator-min-microvolt = <1150000>; + regulator-min-microvolt = <1304000>; regulator-max-microvolt = <1304000>; }; - pm4125_l11: l11 { - regulator-min-microvolt = <970000>; - regulator-max-microvolt = <1150000>; - }; - pm4125_l12: l12 { - regulator-min-microvolt = <875000>; + regulator-min-microvolt = <928000>; regulator-max-microvolt = <975000>; }; pm4125_l13: l13 { regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1950000>; + regulator-max-microvolt = <1800000>; }; pm4125_l14: l14 { - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <1950000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; pm4125_l15: l15 { regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2000000>; + regulator-max-microvolt = <1800000>; }; pm4125_l16: l16 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <2000000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; pm4125_l17: l17 { - regulator-min-microvolt = <2900000>; + regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3544000>; }; pm4125_l18: l18 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l19: l19 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; }; pm4125_l20: l20 { - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <3544000>; + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <2952000>; }; pm4125_l21: l21 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3544000>; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3056000>; }; pm4125_l22: l22 { - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; + regulator-min-microvolt = <3304000>; + regulator-max-microvolt = <3304000>; }; }; }; From a5aeebb68e75d8c23bd6f856201369b988659d16 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Fri, 8 May 2026 10:52:40 +0530 Subject: [PATCH 0853/1058] arm64: dts: qcom: shikra: Add CX power domain to GCC Add CX power domain support to GCC node on Shikra platform. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index a3b981d552bfe..3f1bc7a5cc926 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -807,6 +807,7 @@ <0>, <0>, <0>; + power-domains = <&rpmpd RPMPD_VDDCX>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From 1cd5f4083cc6db7b67695e8fa295e772a65d1bd4 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Fri, 8 May 2026 14:48:36 +0530 Subject: [PATCH 0854/1058] arm64: dts: qcom: Modify compatible for Shikra APCS device Modify compatible for Shikra mailbox APCS device and add fallback compatible string. Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 3f1bc7a5cc926..2e27e4ea7953a 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1413,7 +1413,7 @@ }; apcs_glb: mailbox@f400000 { - compatible = "qcom,shikra-apcs-hmss-global"; + compatible = "qcom,shikra-apss-shared", "qcom,sdm845-apss-shared"; reg = <0x0 0x0f400000 0x0 0x1000>; #mbox-cells = <1>; }; From 4f4b44b6a7f32d911d9c577fe86ec5133ac91be1 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 8 May 2026 21:56:00 +0800 Subject: [PATCH 0855/1058] arm64: dts: qcom: shikra: Add coresight nodes Add DT nodes for the CoreSight debug and trace subsystem on Qualcomm Shikra SoC. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/shikra.dtsi | 1490 ++++++++++++++++++++++++-- 1 file changed, 1388 insertions(+), 102 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 2e27e4ea7953a..63ad89f9f7fde 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -123,6 +123,20 @@ }; }; + dummy-eud { + compatible = "arm,coresight-dummy-sink"; + + label = "eud"; + + in-ports { + port { + eud_in: endpoint { + remote-endpoint = <&replicator_eud_out1>; + }; + }; + }; + }; + firmware { scm { compatible = "qcom,scm-shikra", "qcom,scm"; @@ -138,6 +152,21 @@ reg = <0x0 0xa0000000 0x0 0x0>; }; + modem-etm0 { + compatible = "arm,coresight-dummy-source"; + + label = "modem_etm0"; + arm,static-trace-id = <36>; + + out-ports { + port { + modem_etm0_out: endpoint { + remote-endpoint = <&funnel_in1_in4>; + }; + }; + }; + }; + pmu { compatible = "arm,armv8-pmuv3"; interrupts = ; @@ -2259,150 +2288,1407 @@ }; }; - remoteproc_cdsp: remoteproc@b300000 { - compatible = "qcom,shikra-cdsp-pas"; - reg = <0x0 0x0b300000 0x0 0x100000>; + ctcu@8001000 { + compatible = "qcom,shikra-ctcu","qcom,sa8775p-ctcu"; + reg = <0x0 0x08001000 0x0 0x1000>; - interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>, - <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, - <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, - <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, - <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, - <&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog", - "fatal", - "ready", - "handover", - "stop-ack", - "shutdown-ack"; + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb"; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; - clock-names = "xo"; + in-ports { + port { + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + }; + }; - interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG - &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, - <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG - &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + stm@8002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x0 0x08002000 0x0 0x1000>, + <0x0 0x0e280000 0x0 0x180000>; + reg-names = "stm-base", + "stm-stimulus-base"; - power-domains = <&rpmpd RPMHPD_CX>; + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; - memory-region = <&cdsp_mem>; + out-ports { + port { + stm_out: endpoint { + remote-endpoint = <&funnel_in0_in7>; + }; + }; + }; + }; - qcom,smem-states = <&cdsp_smp2p_out 0>; - qcom,smem-state-names = "stop"; + tpdm@8003000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08003000 0x0 0x1000>; - status = "disabled"; + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; - glink-edge { - interrupts = ; - mboxes = <&apcs_glb 4>; - qcom,remote-pid = <5>; - label = "cdsp"; + label = "tpdm_dcc"; + qcom,cmb-element-bits = <32>; - fastrpc { - compatible = "qcom,fastrpc"; - #address-cells = <1>; - #size-cells = <0>; - label = "cdsp"; - qcom,glink-channels = "fastrpcglink-apps-dsp"; + out-ports { + port { + tpdm_dcc_out: endpoint { + remote-endpoint = <&tpda_qdss_in0>; + }; + }; + }; + }; - compute-cb@1 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <1>; - iommus = <&apps_smmu 0x0201 0x0000>; + tpda@8004000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08004000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_qdss_in0: endpoint { + remote-endpoint = <&tpdm_dcc_out>; }; + }; - compute-cb@2 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <2>; - iommus = <&apps_smmu 0x0202 0x0000>; + port@1 { + reg = <1>; + + tpda_qdss_in1: endpoint { + remote-endpoint = <&tpdm_spdm_out>; }; + }; + }; - compute-cb@3 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <3>; - iommus = <&apps_smmu 0x0203 0x0000>; + out-ports { + port { + tpda_qdss_out: endpoint { + remote-endpoint = <&funnel_in0_in6>; }; + }; + }; + }; - compute-cb@4 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <4>; - iommus = <&apps_smmu 0x0204 0x0000>; + tpdm@800f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x0800f000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_spdm"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_spdm_out: endpoint { + remote-endpoint = <&tpda_qdss_in1>; }; + }; + }; + }; - compute-cb@5 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <5>; - iommus = <&apps_smmu 0x0205 0x0000>; + funnel@8041000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08041000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@5 { + reg = <5>; + + funnel_in0_in5: endpoint { + remote-endpoint = <&snoc_out>; }; + }; - compute-cb@6 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <6>; - iommus = <&apps_smmu 0x0206 0x0000>; + port@6 { + reg = <6>; + + funnel_in0_in6: endpoint { + remote-endpoint = <&tpda_qdss_out>; }; + }; - compute-cb@9 { - compatible = "qcom,fastrpc-compute-cb"; - reg = <9>; - iommus = <&apps_smmu 0x0209 0x0000>; + port@7 { + reg = <7>; + + funnel_in0_in7: endpoint { + remote-endpoint = <&stm_out>; + }; + }; + }; + + out-ports { + port { + funnel_in0_out: endpoint { + remote-endpoint = <&funnel_merg_in0>; }; }; }; }; - remoteproc_lpaicp: remoteproc@b800000 { - compatible = "qcom,shikra-lpaicp-pas"; - reg = <0x0 0x0b800000 0x0 0x200000>; + funnel@8042000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08042000 0x0 0x1000>; - interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING>, - <&lmcu_smp2p_in 0 IRQ_TYPE_NONE>, - <&lmcu_smp2p_in 1 IRQ_TYPE_NONE>, - <&lmcu_smp2p_in 2 IRQ_TYPE_NONE>, - <&lmcu_smp2p_in 3 IRQ_TYPE_NONE>; + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; - interrupt-names = "wdog", - "fatal", - "ready", - "handover", - "stop-ack"; + in-ports { + #address-cells = <1>; + #size-cells = <0>; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; - clock-names = "xo"; + port@1 { + reg = <1>; - memory-region = <&lmcu_mem &lmcu_dtb_mem>; + funnel_in1_in1: endpoint { + remote-endpoint = <&tpda_aodbg_out>; + }; + }; - qcom,smem-states = <&lmcu_smp2p_out 0>; - qcom,smem-state-names = "stop"; + port@4 { + reg = <4>; - status = "disabled"; + funnel_in1_in4: endpoint { + remote-endpoint = <&modem_etm0_out>; + }; + }; - glink-edge { - interrupts = ; - mboxes = <&apcs_glb 9>; - qcom,remote-pid = <26>; - label = "lpaicp"; + port@6 { + reg = <6>; + + funnel_in1_in6: endpoint { + remote-endpoint = <&funnel_cpuss1_out>; + }; + }; + + port@7 { + reg = <7>; + + funnel_in1_in7: endpoint { + remote-endpoint = <&funnel_center_out>; + }; + }; + }; + + out-ports { + port { + funnel_in1_out: endpoint { + remote-endpoint = <&funnel_merg_in1>; + }; + }; }; }; - cpufreq_hw: cpufreq@fd91000 { - compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; - reg = <0x0 0x0fd91000 0x0 0x1000>, - <0x0 0x0fd92000 0x0 0x1000>; - reg-names = "freq-domain0", - "freq-domain1"; + funnel@8045000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08045000 0x0 0x1000>; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; - clock-names = "xo", "alternate"; + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; - interrupts = , - ; - interrupt-names = "dcvsh-irq-0", - "dcvsh-irq-1"; + in-ports { + #address-cells = <1>; + #size-cells = <0>; - #freq-domain-cells = <1>; + port@0 { + reg = <0>; + + funnel_merg_in0: endpoint { + remote-endpoint = <&funnel_in0_out>; + }; + }; + + port@1 { + reg = <1>; + + funnel_merg_in1: endpoint { + remote-endpoint = <&funnel_in1_out>; + }; + }; + }; + + out-ports { + port { + funnel_merg_out: endpoint { + remote-endpoint = <&tmc_etf_in>; + }; + }; + }; + }; + + replicator@8046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x08046000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_qdss_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_qdss_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_qdss_out1: endpoint { + remote-endpoint = <&replicator_eud_in>; + }; + }; + }; + }; + + tmc@8047000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x08047000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + tmc_etf_in: endpoint { + remote-endpoint = <&funnel_merg_out>; + }; + }; + }; + + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&replicator_qdss_in>; + }; + }; + }; + }; + + tmc@8048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x08048000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0160 0x0>; + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&replicator_qdss_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; }; + replicator@804a000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x0804a000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_eud_in: endpoint { + remote-endpoint = <&replicator_qdss_out1>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + replicator_eud_out1: endpoint { + remote-endpoint = <&eud_in>; + }; + }; + }; + }; + + tpdm@8800000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08800000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_cdsp"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <4>; + + out-ports { + port { + tpdm_cdsp_out: endpoint { + remote-endpoint = <&funnel_cdsp_in0>; + }; + }; + }; + }; + + funnel@8801000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08801000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_cdsp_in0: endpoint { + remote-endpoint = <&tpdm_cdsp_out>; + }; + }; + }; + + out-ports { + port { + funnel_cdsp_out0: endpoint { + remote-endpoint = <&tpda_center_in3>; + }; + }; + }; + }; + + cti@8807000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08807000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_turing_q6"; + }; + + cti@8833000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08833000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_mss_q6"; + }; + + tpdm@8840000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08840000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_vsense"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_vsense_out: endpoint { + remote-endpoint = <&tpda_center_in6>; + }; + }; + }; + }; + + tpdm@8844000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08844000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_dlct_1"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_dlct_1_out: endpoint { + remote-endpoint = <&tpda_center_in13>; + }; + }; + }; + }; + + tpda@8845000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08845000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_center_in0: endpoint { + remote-endpoint = <&funnel_mcu_out>; + }; + }; + + port@2 { + reg = <2>; + + tpda_center_in2: endpoint { + remote-endpoint = <&tpdm_dlct_out>; + }; + }; + + port@3 { + reg = <3>; + + tpda_center_in3: endpoint { + remote-endpoint = <&funnel_cdsp_out0>; + }; + }; + + port@4 { + reg = <4>; + + tpda_center_in4: endpoint { + remote-endpoint = <&funnel_ddr_out0>; + }; + }; + + port@6 { + reg = <6>; + + tpda_center_in6: endpoint { + remote-endpoint = <&tpdm_vsense_out>; + }; + }; + + port@7 { + reg = <7>; + + tpda_center_in7: endpoint { + remote-endpoint = <&tpdm_prng_out>; + }; + }; + + port@8 { + reg = <8>; + + tpda_center_in8: endpoint { + remote-endpoint = <&tpdm_west_out>; + }; + }; + + port@9 { + reg = <9>; + + tpda_center_in9: endpoint { + remote-endpoint = <&tpdm_qm_out>; + }; + }; + + port@a { + reg = <0xa>; + + tpda_center_in10: endpoint { + remote-endpoint = <&tpdm_pimem_out>; + }; + }; + + port@d { + reg = <0xd>; + + tpda_center_in13: endpoint { + remote-endpoint = <&tpdm_dlct_1_out>; + }; + }; + }; + + out-ports { + port { + tpda_center_out: endpoint { + remote-endpoint = <&funnel_center_in0>; + }; + }; + }; + }; + + funnel@8846000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08846000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_center_in0: endpoint { + remote-endpoint = <&tpda_center_out>; + }; + }; + }; + + out-ports { + port { + funnel_center_out: endpoint { + remote-endpoint = <&funnel_in1_in7>; + }; + }; + }; + }; + + tpdm@884c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x0884c000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_prng"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_prng_out: endpoint { + remote-endpoint = <&tpda_center_in7>; + }; + }; + }; + }; + + tpdm@8850000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08850000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_pimem"; + qcom,cmb-element-bits = <64>; + qcom,dsb-element-bits = <32>; + + out-ports { + port { + tpdm_pimem_out: endpoint { + remote-endpoint = <&tpda_center_in10>; + }; + }; + }; + }; + + tpdm@8980000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08980000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_mcu"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_mcu_out: endpoint { + remote-endpoint = <&funnel_mcu_in0>; + }; + }; + }; + }; + + funnel@8982000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08982000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_mcu_in0: endpoint { + remote-endpoint = <&tpdm_mcu_out>; + }; + }; + }; + + out-ports { + port { + funnel_mcu_out: endpoint { + remote-endpoint = <&tpda_center_in0>; + }; + }; + }; + }; + + tpdm@89d0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x089d0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_qm"; + qcom,dsb-element-bits = <32>; + + out-ports { + port { + tpdm_qm_out: endpoint { + remote-endpoint = <&tpda_center_in9>; + }; + }; + }; + }; + + tpdm@8a01000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08a01000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_mapss"; + qcom,cmb-element-bits = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_mapss_out: endpoint { + remote-endpoint = <&tpda_aodbg_in>; + }; + }; + }; + }; + + cti@8a02000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08a02000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_mapss"; + }; + + tpda@8a04000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08a04000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + tpda_aodbg_in: endpoint { + remote-endpoint = <&tpdm_mapss_out>; + }; + }; + }; + + out-ports { + port { + tpda_aodbg_out: endpoint { + remote-endpoint = <&funnel_in1_in1>; + }; + }; + }; + }; + + tpdm@8a58000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08a58000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_west"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_west_out: endpoint { + remote-endpoint = <&tpda_center_in8>; + }; + }; + }; + }; + + cti@8b30000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b30000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_cortex_m3"; + }; + + tpdm@8b58000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08b58000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_dlct"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_dlct_out: endpoint { + remote-endpoint = <&tpda_center_in2>; + }; + }; + }; + }; + + cti@8b59000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b59000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_0"; + }; + + cti@8b5a000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5a000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_1"; + }; + + cti@8b5b000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5b000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_2"; + }; + + cti@8b5c000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5c000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_3"; + }; + + tpdm@8b60000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08b60000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_ddr"; + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <1>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_ddr_out: endpoint { + remote-endpoint = <&funnel_ddr_in0>; + }; + }; + }; + }; + + cti@8b62000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b62000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_0"; + }; + + funnel@8b65000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08b65000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_ddr_in0: endpoint { + remote-endpoint = <&tpdm_ddr_out>; + }; + }; + }; + + out-ports { + port { + funnel_ddr_out0: endpoint { + remote-endpoint = <&tpda_center_in4>; + }; + }; + }; + }; + + cti@8b70000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b70000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_0_1"; + }; + + cti@8b71000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b71000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_1_1"; + }; + + cti@9020000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09020000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe0"; + }; + + etm@9040000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09040000 0x0 0x1000>; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in0>; + }; + }; + }; + }; + + cti@90e0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x090e0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_cluster"; + }; + + cti@9120000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09120000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe1"; + }; + + etm@9140000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09140000 0x0 0x1000>; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in1>; + }; + }; + }; + }; + + cti@9220000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09220000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe2"; + }; + + etm@9240000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09240000 0x0 0x1000>; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in2>; + }; + }; + }; + }; + + cti@9320000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09320000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe3"; + }; + + etm@9340000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09340000 0x0 0x1000>; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in3>; + }; + }; + }; + }; + + funnel@9800000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x09800000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_cpuss0_in0: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + + port@1 { + reg = <1>; + + funnel_cpuss0_in1: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + + port@2 { + reg = <2>; + + funnel_cpuss0_in2: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + + port@3 { + reg = <3>; + + funnel_cpuss0_in3: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + funnel_cpuss0_out: endpoint { + remote-endpoint = <&funnel_cpuss1_in0>; + }; + }; + }; + }; + + funnel@9810000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x09810000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_cpuss1_in0: endpoint { + remote-endpoint = <&funnel_cpuss0_out>; + }; + }; + + port@3 { + reg = <3>; + + funnel_cpuss1_in3: endpoint { + remote-endpoint = <&tpda_apss_out>; + }; + }; + }; + + out-ports { + port { + funnel_cpuss1_out: endpoint { + remote-endpoint = <&funnel_in1_in6>; + }; + }; + }; + }; + + cti@982b000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x0982b000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_riscv"; + }; + + tpdm@9860000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x09860000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_actpm"; + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <1>; + + out-ports { + port { + tpdm_actpm_out: endpoint { + remote-endpoint = <&tpda_apss_in2>; + }; + }; + }; + }; + + tpdm@9861000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x09861000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_hwe"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_hwe_out: endpoint { + remote-endpoint = <&tpda_apss_in3>; + }; + }; + }; + }; + + tpda@9863000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x09863000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_apss_in0: endpoint { + remote-endpoint = <&tpdm_llm_silver_out>; + }; + }; + + port@2 { + reg = <2>; + + tpda_apss_in2: endpoint { + remote-endpoint = <&tpdm_actpm_out>; + }; + }; + + port@3 { + reg = <3>; + + tpda_apss_in3: endpoint { + remote-endpoint = <&tpdm_hwe_out>; + }; + }; + }; + + out-ports { + port { + tpda_apss_out: endpoint { + remote-endpoint = <&funnel_cpuss1_in3>; + }; + }; + }; + }; + + tpdm@98a0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x098a0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_llm_silver"; + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <12>; + + out-ports { + port { + tpdm_llm_silver_out: endpoint { + remote-endpoint = <&tpda_apss_in0>; + }; + }; + }; + }; + + cti@98e0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x098e0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_0"; + }; + + cti@98f0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x098f0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_1"; + }; + + cti@9900000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09900000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_2"; + }; + + remoteproc_cdsp: remoteproc@b300000 { + compatible = "qcom,shikra-cdsp-pas"; + reg = <0x0 0x0b300000 0x0 0x100000>; + + interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + + power-domains = <&rpmpd RPMHPD_CX>; + + memory-region = <&cdsp_mem>; + + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 4>; + qcom,remote-pid = <5>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,fastrpc"; + #address-cells = <1>; + #size-cells = <0>; + label = "cdsp"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x0201 0x0000>; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x0202 0x0000>; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x0203 0x0000>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x0204 0x0000>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x0205 0x0000>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x0206 0x0000>; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu 0x0209 0x0000>; + }; + }; + }; + }; + + remoteproc_lpaicp: remoteproc@b800000 { + compatible = "qcom,shikra-lpaicp-pas"; + reg = <0x0 0x0b800000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING>, + <&lmcu_smp2p_in 0 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 1 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 2 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 3 IRQ_TYPE_NONE>; + + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + memory-region = <&lmcu_mem &lmcu_dtb_mem>; + + qcom,smem-states = <&lmcu_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 9>; + qcom,remote-pid = <26>; + label = "lpaicp"; + }; + }; + + cpufreq_hw: cpufreq@fd91000 { + compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; + reg = <0x0 0x0fd91000 0x0 0x1000>, + <0x0 0x0fd92000 0x0 0x1000>; + reg-names = "freq-domain0", + "freq-domain1"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + interrupts = , + ; + interrupt-names = "dcvsh-irq-0", + "dcvsh-irq-1"; + + #freq-domain-cells = <1>; + }; + }; + + snoc { + compatible = "arm,coresight-dummy-source"; + arm,static-trace-id = <18>; + + label = "snoc"; + + out-ports { + port { + snoc_out: endpoint { + remote-endpoint = <&funnel_in0_in5>; + }; + }; + }; }; thermal_zones: thermal-zones { From 5258e838b37dae4c6472c83afbc31fe78fd374a8 Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Wed, 13 May 2026 12:17:18 +0530 Subject: [PATCH 0856/1058] arm64: dts: qcom: shikra: Enable BT support on EVK boards. Enable uart8 and add WCN3988 Bluetooth node with board-specific regulator supplies across CQM, CQS and IQS Shikra EVK variants. Signed-off-by: Yepuri Siddu --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 12 ++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 12 ++++++++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 12 ++++++++++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 8 ++++++++ 4 files changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index e864b995443ef..05b450bd2acdf 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -18,6 +18,7 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; + serial1 = &uart8; }; chosen { @@ -88,6 +89,17 @@ status = "okay"; }; +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + }; +}; + &usb_1 { dr_mode = "otg"; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 47f0dfeb6b627..d12c897a9e71f 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -18,6 +18,7 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; + serial1 = &uart8; }; chosen { @@ -82,6 +83,17 @@ status = "okay"; }; +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + }; +}; + &usb_1 { dr_mode = "otg"; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 52862e4e2f57d..fb60b0a5ba0ab 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -18,6 +18,7 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; + serial1 = &uart8; }; chosen { @@ -84,6 +85,17 @@ status = "okay"; }; +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&pm8150_s4>; + vddxo-supply = <&pm8150_l12>; + vddrf-supply = <&pm8150_l8>; + vddch0-supply = <&vreg_wlan_3p3_dummy>; + }; +}; + &usb_1 { dr_mode = "peripheral"; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 63ad89f9f7fde..83438dcb0df1b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2189,6 +2189,14 @@ pinctrl-names = "default"; status = "disabled"; + + bluetooth { + compatible = "qcom,wcn3988-bt"; + + enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + max-speed = <3200000>; + }; + }; i2c9: i2c@4aa4000 { From 824666825626359ca4898d811f938d8421a81eaa Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 11 May 2026 16:00:01 +0530 Subject: [PATCH 0857/1058] arm64: dts: qcom: shikra: Add MDSS display subsystem Add the SoC-level display subsystem nodes for Shikra: MDSS wrapper, DPU display controller, DSI host controller, and 14nm DSI PHY. Shikra uses DPU 6.5 hardware (same as QCM2290), with platform-specific compatibles qcom,shikra-dpu and qcom,shikra-dsi-ctrl. The dispcc clock inputs for the DSI byte and pixel PLLs are wired from mdss_dsi0_phy. Signed-off-by: Mahadevan P --- arch/arm64/boot/dts/qcom/shikra.dtsi | 202 ++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 83438dcb0df1b..33ca25579710e 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -1298,14 +1299,211 @@ }; }; + mdss: display-subsystem@5e00000 { + compatible = "qcom,shikra-mdss"; + reg = <0x0 0x05e00000 0x0 0x1000>; + reg-names = "mdss"; + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", + "bus", + "core"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>; + + iommus = <&apps_smmu 0x420 0x2>; + interconnects = <&mmrt_virt MASTER_MDP_PORT0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_DISPLAY_CFG RPM_ALWAYS_TAG>; + interconnect-names = "mdp0-mem", + "cpu-cfg"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdp: display-controller@5e01000 { + compatible = "qcom,shikra-dpu"; + reg = <0x0 0x05e01000 0x0 0x8f000>, + <0x0 0x05eb0000 0x0 0x3000>; + reg-names = "mdp", + "vbif"; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "iface", + "core", + "lut", + "vsync"; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-192000000 { + opp-hz = /bits/ 64 <192000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + + mdss_dsi0: dsi@5e94000 { + compatible = "qcom,shikra-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x0 0x05e94000 0x0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; + assigned-clock-parents = <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + phys = <&mdss_dsi0_phy>; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-164000000 { + opp-hz = /bits/ 64 <164000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi0_out: endpoint { + }; + }; + }; + }; + + mdss_dsi0_phy: phy@5e94400 { + compatible = "qcom,dsi-phy-14nm-2290"; + reg = <0x0 0x05e94400 0x0 0x100>, + <0x0 0x05e94500 0x0 0x300>, + <0x0 0x05e94800 0x0 0x188>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "ref"; + + power-domains = <&rpmpd QCM2290_VDDMX>; + required-opps = <&rpmpd_opp_nom>; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + }; + dispcc: clock-controller@5f00000 { compatible = "qcom,shikra-dispcc"; reg = <0x0 0x05f00000 0x0 0x20000>; clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, - <0>, - <0>, + <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>, <0>, <0>; #clock-cells = <1>; From 70faa7d45269403574a79b3355743eba6d0ef859 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 11 May 2026 16:00:45 +0530 Subject: [PATCH 0858/1058] arm64: dts: qcom: shikra-cqm-evk: Enable display and add DLC0697 panel Enable the Shikra MDSS display subsystem on the CQM EVK board and add the DLC0697 panel node. Pin pm4125_l5 to 1.232V with regulator-allow-set-load for DSI PHY PLL stability. Signed-off-by: Mahadevan P --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 90 +++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 05b450bd2acdf..a8f6d64ea57df 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -24,6 +24,65 @@ chosen { stdout-path = "serial0:115200n8"; }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm4125_l17>; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + +}; + +&mdss { + status = "okay"; +}; + +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + enable-gpios = <&tlmm 91 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm4125_l15>; + bias-supply = <&lcd_bias>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; }; &pm4125_hs_in { @@ -85,6 +144,37 @@ status = "okay"; }; +&tlmm { + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; + +}; + &uart0 { status = "okay"; }; From d8d2a848da80cf1d0e7ba72b3b92222483be05ac Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Fri, 15 May 2026 00:31:40 +0530 Subject: [PATCH 0859/1058] FROMLIST: arm64: dts: qcom: shikra: Add qcrypto node support Add qcrypto and cryptobam support for shikra target. Link: https://lore.kernel.org/lkml/20260515-shikra_qcrypto-v1-3-80f07b345c29@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 33ca25579710e..512ff4348d73d 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -947,6 +947,41 @@ #interconnect-cells = <2>; }; + cryptobam: dma-controller@1b04000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0x0 0x01b04000 0x0 0x24000>; + interrupts = ; + #dma-cells = <1>; + iommus = <&apps_smmu 0x84 0x0011>, + <&apps_smmu 0x86 0x0011>, + <&apps_smmu 0x92 0x0>, + <&apps_smmu 0x94 0x0011>, + <&apps_smmu 0x96 0x0011>, + <&apps_smmu 0x98 0x0001>, + <&apps_smmu 0x9F 0x0>; + qcom,ee = <0>; + qcom,controlled-remotely; + num-channels = <16>; + qcom,num-ees = <4>; + }; + + crypto: crypto@1b3a000 { + compatible = "qcom,shikra-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0x0 0x01b3a000 0x0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x84 0x0011>, + <&apps_smmu 0x86 0x0011>, + <&apps_smmu 0x92 0x0>, + <&apps_smmu 0x94 0x0011>, + <&apps_smmu 0x96 0x0011>, + <&apps_smmu 0x98 0x0001>, + <&apps_smmu 0x9F 0x0>; + interconnects = <&system_noc MASTER_CRYPTO_CORE0 0 + &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "memory"; + }; + qfprom: efuse@1b40000 { compatible = "qcom,shikra-qfprom", "qcom,qfprom"; reg = <0x0 0x01b40000 0x0 0x700>; From 37943afb5669ca17bfa0dfcded2846576d021f64 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Thu, 14 May 2026 18:29:49 +0530 Subject: [PATCH 0860/1058] FROMLIST: arm64: dts: qcom: shikra: Add TRNG support Add True Random Number Generator(TRNG) node for shikra. Link: https://lore.kernel.org/lkml/20260514-shikra_rng-v1-2-4ea721a1429a@oss.qualcomm.com/ Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 512ff4348d73d..4ddb00de141cf 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1033,6 +1033,11 @@ #thermal-sensor-cells = <1>; }; + rng: rng@4454000 { + compatible = "qcom,shikra-trng", "qcom,trng"; + reg = <0 0x04454000 0 0x1000>; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; From 5c4f897b8f95db933ac32e5d2e36ffa3d20d4151 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Wed, 13 May 2026 18:10:02 +0530 Subject: [PATCH 0861/1058] FROMLIST: arm64: dts: qcom: shikra: Enable ice support Add UFS inline crypto engine(ICE) support for shikra. Link: https://lore.kernel.org/lkml/20260515-shikra_ice_ufs-v1-2-b1b6ced70559@oss.qualcomm.com Signed-off-by: Kuldeep Singh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 4ddb00de141cf..93bade11c092a 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1099,6 +1099,7 @@ mmc-hs400-enhanced-strobe; resets = <&gcc GCC_SDCC1_BCR>; + qcom,ice = <&sdhc_ice>; status = "disabled"; @@ -1780,6 +1781,17 @@ iommus = <&apps_smmu 0xf6 0x0>; }; + sdhc_ice: crypto@4748000 { + compatible = "qcom,shikra-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x04748000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmpd RPMHPD_CX>; + }; + qupv3_0: geniqup@4ac0000 { compatible = "qcom,geni-se-qup"; reg = <0x0 0x04ac0000 0x0 0x2000>; From 7237cd61114624fe57d00465b933b5f90df6b037 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Thu, 14 May 2026 16:35:39 +0530 Subject: [PATCH 0862/1058] arm64: dts: qcom: shikra: Add pm4125 s1 regulator Add pm4125_s1 regulator node at fixed 1.396V to both shikra-cqm-som and shikra-cqs-som. This rail is used by the audio subsystem. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 5 +++++ arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 107dcb442f0d8..047e93245def4 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -176,6 +176,11 @@ regulators { compatible = "qcom,rpm-pm2250-regulators"; + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1396000>; + }; + pm4125_s2: s2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1200000>; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index 8094df7e607e1..89580d7699118 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -177,6 +177,11 @@ regulators { compatible = "qcom,rpm-pm2250-regulators"; + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1396000>; + }; + pm4125_s2: s2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1200000>; From bd67b643c3c2c630febbeeb68c4eb1f12a69724f Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Thu, 14 May 2026 20:08:12 +0530 Subject: [PATCH 0863/1058] arm64: dts: qcom: Add dedicated BT 3.3V dummy regulator. Add a separate fixed dummy regulator for Bluetooth. Signed-off-by: Yepuri Siddu --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index fb60b0a5ba0ab..63136008f410b 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -34,6 +34,14 @@ regulator-always-on; }; }; + + vreg_bt_3p3_dummy: regulator-bt-3p3-dummy { + compatible = "regulator-fixed"; + regulator-name = "bt_3p3_dummy"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; }; &remoteproc_cdsp { @@ -92,7 +100,7 @@ vddio-supply = <&pm8150_s4>; vddxo-supply = <&pm8150_l12>; vddrf-supply = <&pm8150_l8>; - vddch0-supply = <&vreg_wlan_3p3_dummy>; + vddch0-supply = <&vreg_bt_3p3_dummy>; }; }; From f55932d11c405d7cd43412843376de25acf1d09c Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Fri, 15 May 2026 15:09:42 +0530 Subject: [PATCH 0864/1058] arm64: dts: qcom: shikra-cqs-evk: Enable display Enable the DLC0697 MIPI DSI display panel on the Shikra CQS EVK. Signed-off-by: Mahadevan P --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 95 ++++++++++++++++++++- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index d12c897a9e71f..41e77f0601ce6 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -24,12 +24,70 @@ chosen { stdout-path = "serial0:115200n8"; }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm4125_l17>; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + enable-gpios = <&tlmm 91 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm4125_l15>; + bias-supply = <&lcd_bias>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; }; &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + &pm4125_ss_in { remote-endpoint = <&usb_qmpphy_out>; }; @@ -79,6 +137,36 @@ status = "okay"; }; +&tlmm { + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; +}; + &uart0 { status = "okay"; }; @@ -119,6 +207,10 @@ status = "okay"; }; +&usb_qmpphy_out { + remote-endpoint = <&pm4125_ss_in>; +}; + &wifi { vdd-0.8-cx-mx-supply = <&pm4125_l7>; vdd-1.8-xo-supply = <&pm4125_l13>; @@ -130,6 +222,3 @@ status = "okay"; }; -&usb_qmpphy_out { - remote-endpoint = <&pm4125_ss_in>; -}; From 50bf084d368e890af92ec9ac62f553f21961f0de Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 7 May 2026 14:04:46 +0530 Subject: [PATCH 0865/1058] arm64: dts: qcom: Add AudioCoreCC node support on Shikra Enable AudioCore Clock Controller (AudioCoreCC) support on Shikra platform. The Shikra CQM variant requires both clock and reset support, while the Shikra CQS variant requires only reset support. Hence, add support to configure the respective device tree nodes accordingly. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 5 +++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 13 +++++++++++++ 3 files changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 047e93245def4..03e04ce05efe1 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -53,6 +53,10 @@ }; }; +&audiocorecc { + status = "okay"; +}; + &pm4125_adc { pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index 89580d7699118..2c1788c3b88bd 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -54,6 +54,11 @@ }; }; +&audiocorecc { + compatible = "qcom,shikra-cqs-audiocorecc"; + status = "okay"; +}; + &pm4125_adc { pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 93bade11c092a..8e50838bcdb22 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -3789,6 +3790,18 @@ label = "cti_apss_2"; }; + audiocorecc: clock-controller@a0a0000 { + compatible = "qcom,shikra-cqm-audiocorecc"; + reg = <0x0 0x0a0a0000 0x0 0x10000>, + <0x0 0x0a0b4000 0x0 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + status = "disabled"; + }; + remoteproc_cdsp: remoteproc@b300000 { compatible = "qcom,shikra-cdsp-pas"; reg = <0x0 0x0b300000 0x0 0x100000>; From e7d4f4b2fff344a5a74e0e86d1dfc1de95dd66a5 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 18 May 2026 11:42:17 +0530 Subject: [PATCH 0866/1058] arm64: dts: qcom: Fix pm4125 vbus regulator compatible and constraints Remove pm8150b fallback compatible from pm4125_vbus and fix regulator constraints in shikra SOM DTS files to use microvolt instead of microamp. Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/pm4125.dtsi | 2 +- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pm4125.dtsi b/arch/arm64/boot/dts/qcom/pm4125.dtsi index 7113504d5941a..829a77fb1e5cb 100644 --- a/arch/arm64/boot/dts/qcom/pm4125.dtsi +++ b/arch/arm64/boot/dts/qcom/pm4125.dtsi @@ -37,7 +37,7 @@ }; pm4125_vbus: usb-vbus-regulator@1100 { - compatible = "qcom,pm4125-vbus-reg", "qcom,pm8150b-vbus-reg"; + compatible = "qcom,pm4125-vbus-reg"; reg = <0x1100>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 03e04ce05efe1..1bf69cb7d1058 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -167,8 +167,8 @@ }; &pm4125_vbus { - regulator-min-microamp = <500000>; - regulator-max-microamp = <500000>; + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi index 2c1788c3b88bd..e46dcf401d7c5 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -169,8 +169,8 @@ }; &pm4125_vbus { - regulator-min-microamp = <500000>; - regulator-max-microamp = <500000>; + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; status = "okay"; }; From 14531398fdb1587297a96dfeec021db91c5ca94b Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Mon, 18 May 2026 18:39:34 +0530 Subject: [PATCH 0867/1058] arm64: dts: qcom: shikra: Enable MPSS remoteproc Enable the Modem Processor SubSystem (MPSS) remoteproc on Shikra CQS and IQS EVK boards Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 6 ++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 41e77f0601ce6..f8d9d4ad81f80 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -105,6 +105,12 @@ status = "okay"; }; +&remoteproc_mpss { + firmware-name = "qcom/shikra/qdsp6sw.mbn"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 63136008f410b..388b006a854b5 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -57,6 +57,12 @@ status = "okay"; }; +&remoteproc_mpss { + firmware-name = "qcom/shikra/qdsp6sw.mbn"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm8150_l17>; vqmmc-supply = <&pm8150_s4>; From 0b89517063ae2699a769f9cf61a801ef6b5c85d8 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 20 May 2026 15:46:08 +0530 Subject: [PATCH 0868/1058] arm64: dts: qcom: shikra: Add DDR BWMON support Add CPU-to-DDR BWMON nodes and their corresponding opp tables for Shikra SoC. This is necessary to enable power management and optimize system performance from the perspective of dynamically changing DDR frequencies. Signed-off-by: Sayantan Chakraborty Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 8e50838bcdb22..21352c107f0a8 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -810,6 +810,46 @@ }; }; + pmu@c91000 { + compatible = "qcom,shikra-cpu-bwmon", "qcom,sc7280-llcc-bwmon"; + reg = <0x0 0x00c91000 0x0 0x1000>; + + interrupts = ; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>; + + operating-points-v2 = <&cpu_bwmon_opp_table>; + + cpu_bwmon_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <1200000>; + }; + + opp-1 { + opp-peak-kBps = <2188000>; + }; + + opp-2 { + opp-peak-kBps = <3072000>; + }; + + opp-3 { + opp-peak-kBps = <4068000>; + }; + + opp-4 { + opp-peak-kBps = <6220000>; + }; + + opp-5 { + opp-peak-kBps = <7216000>; + }; + }; + }; + mem_noc: interconnect@d00000 { compatible = "qcom,shikra-mem-noc-core"; reg = <0x0 0x00d00000 0x0 0x43080>; From deb63f04d880bb72bba7fa72f2aaac02faadf436 Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 20 May 2026 19:47:15 +0530 Subject: [PATCH 0869/1058] arm64: dts: qcom: shikra: Add EPSS L3 interconnect provider node Add Epoch Subsystem (EPSS) L3 interconnect provider node for Shikra SoC. Signed-off-by: Raviteja Laggyshetty --- arch/arm64/boot/dts/qcom/shikra.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 21352c107f0a8..fc1a38f91134b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -3968,6 +3969,14 @@ }; }; + epss_l3: interconnect@fd90000 { + compatible = "qcom,shikra-epss-l3"; + reg = <0x0 0x0fd90000 0x0 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + #interconnect-cells = <1>; + }; + cpufreq_hw: cpufreq@fd91000 { compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; reg = <0x0 0x0fd91000 0x0 0x1000>, From 415e65d0d55536fdaf3d4dc96f32f480cabe4e57 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 19 May 2026 12:21:14 +0530 Subject: [PATCH 0870/1058] arm64: dts: qcom: shikra: Add BAM-DMUX support Add required nodes to enable the upstream BAM-DMUX WWAN driver on Shikra. The SMSM (Shared Memory State Machine) node provides the power control signaling between the AP and modem for BAM-DMUX. The BAM DMA controller node describes the A2 modem BAM hardware as a standard DMA controller. The BAM-DMUX node references the DMA channels and the pc/pc-ack interrupt lines from the modem SMSM entry for power control signaling. Signed-off-by: Vishnu Santhosh --- arch/arm64/boot/dts/qcom/shikra.dtsi | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index fc1a38f91134b..86ce8edb44bf2 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -24,6 +24,23 @@ #address-cells = <2>; #size-cells = <2>; + bam_dmux: bam-dmux { + compatible = "qcom,bam-dmux"; + + interrupts-extended = + <&modem_smsm 1 IRQ_TYPE_EDGE_BOTH>, + <&modem_smsm 11 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "pc", "pc-ack"; + + qcom,smem-states = + <&apps_smsm 1>, + <&apps_smsm 11>; + qcom,smem-state-names = "pc", "pc-ack"; + + dmas = <&bam_dmux_dma 4>, <&bam_dmux_dma 5>; + dma-names = "tx", "rx"; + }; + clocks { xo_board: xo-board { compatible = "fixed-clock"; @@ -418,6 +435,28 @@ }; }; + smsm { + compatible = "qcom,smsm"; + + #address-cells = <1>; + #size-cells = <0>; + + mboxes = <0>, <&apcs_glb 13>; + + apps_smsm: apps@0 { + reg = <0>; + #qcom,smem-state-cells = <1>; + }; + + modem_smsm: modem@1 { + reg = <1>; + interrupts = ; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; @@ -2546,6 +2585,18 @@ }; }; + bam_dmux_dma: dma-controller@6044000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x0 0x06044000 0x0 0x19000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + + num-channels = <6>; + qcom,num-ees = <1>; + qcom,powered-remotely; + }; + remoteproc_mpss: remoteproc@6080000 { compatible = "qcom,shikra-mpss-pas"; reg = <0x0 0x06080000 0x0 0x100>; From d095baa33aade56505fc68c5be930ac27c6802e7 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 12 May 2026 12:17:18 +0530 Subject: [PATCH 0871/1058] arm64: dts: qcom: shikra: Add CAMSS node Add node for the Shikra camera subsystem. Co-developed-by: Vikram Sharma Signed-off-by: Vikram Sharma Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/shikra.dtsi | 100 +++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 86ce8edb44bf2..a523f47a2165f 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1421,6 +1421,106 @@ }; }; + camss: camss@5c11000 { + compatible = "qcom,shikra-camss"; + + reg = <0x0 0x05c11000 0x0 0x1000>, + <0x0 0x05c6e000 0x0 0x1000>, + <0x0 0x05c75000 0x0 0x1000>, + <0x0 0x05c52000 0x0 0x1000>, + <0x0 0x05c53000 0x0 0x1000>, + <0x0 0x05c66000 0x0 0x400>, + <0x0 0x05c68000 0x0 0x400>, + <0x0 0x05c6f000 0x0 0x4000>, + <0x0 0x05c76000 0x0 0x4000>; + reg-names = "top", + "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_RT_AXI_CLK>, + <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, + <&gcc GCC_CAMSS_CPHY_0_CLK>, + <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>, + <&gcc GCC_CAMSS_CPHY_1_CLK>, + <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_1_CLK>, + <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>; + clock-names = "ahb", + "axi", + "camnoc_nrt_axi", + "camnoc_rt_axi", + "csi0", + "csi1", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "top_ahb", + "vfe0", + "vfe0_cphy_rx", + "vfe1", + "vfe1_cphy_rx"; + + interrupts = , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmrt_virt MASTER_CAMNOC_HF RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc"; + + iommus = <&apps_smmu 0x400 0x0>; + + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + }; + }; + mdss: display-subsystem@5e00000 { compatible = "qcom,shikra-mdss"; reg = <0x0 0x05e00000 0x0 0x1000>; From 638b4322248d98b6d0ca1693f89cf5309406a3d8 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 12 May 2026 13:42:31 +0530 Subject: [PATCH 0872/1058] arm64: dts: qcom: shikra: Add CCI definitions Qualcomm Shikra SoC has one Camera Control Interface (CCI) containing two I2C hosts. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/shikra.dtsi | 67 ++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index a523f47a2165f..bb38bb64959e4 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -491,6 +491,38 @@ gpio-ranges = <&tlmm 0 0 165>; wakeup-parent = <&mpm>; + cci_i2c0_default: cci-i2c0-default-state { + /* SDA, SCL */ + pins = "gpio36", "gpio37"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + cci_i2c0_sleep: cci-i2c0-sleep-state { + /* SDA, SCL */ + pins = "gpio36", "gpio37"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-down; + }; + + cci_i2c1_default: cci-i2c1-default-state { + /* SDA, SCL */ + pins = "gpio41", "gpio42"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + cci_i2c1_sleep: cci-i2c1-sleep-state { + /* SDA, SCL */ + pins = "gpio41", "gpio42"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-down; + }; + qup_i2c0_data_clk: qup-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio2", "gpio3"; @@ -1521,6 +1553,41 @@ }; }; + cci: cci@5c1b000 { + compatible = "qcom,shikra-cci", "qcom,msm8996-cci"; + + reg = <0x0 0x05c1b000 0x0 0x1000>; + interrupts = ; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_CCI_0_CLK>; + clock-names = "ahb", + "cci"; + + pinctrl-0 = <&cci_i2c0_default &cci_i2c1_default>; + pinctrl-1 = <&cci_i2c0_sleep &cci_i2c1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + mdss: display-subsystem@5e00000 { compatible = "qcom,shikra-mdss"; reg = <0x0 0x05e00000 0x0 0x1000>; From 997fa2247ff4d03a8e9ddf835a629eff810aa183 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 12 May 2026 14:08:40 +0530 Subject: [PATCH 0873/1058] arm64: dts: qcom: shikra: Add pin configuration for mclks Add pinctrl configuration for the four available camera master clocks. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/shikra.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index bb38bb64959e4..824d4ca0c409e 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -523,6 +523,34 @@ bias-pull-down; }; + mclk0_default: mclk0-default-state { + pins = "gpio34"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk1_default: mclk1-default-state { + pins = "gpio35"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk2_default: mclk2-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk3_default: mclk3-default-state { + pins = "gpio98"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + qup_i2c0_data_clk: qup-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio2", "gpio3"; From 861fd779aedcd14d44b7ca94bdc14d7f8a0ee966 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 22 May 2026 12:24:49 +0530 Subject: [PATCH 0874/1058] arm64: dts: qcom: shikra-cqm-evk-imx577-camera: Add DT overlay Shikra CQM and CQS are retail variants sharing the same PM4125 PMIC and identical camera supply rails. The only difference between them is the integrated modem on CQM, which does not affect camera hardware. Add a shared overlay for optional IMX577 integration via CSIPHY1, used by both CQM and CQS EVK boards. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/Makefile | 6 ++ .../qcom/shikra-cqm-evk-imx577-camera.dtso | 63 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a9e9d829fb962..df41830e18edf 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -337,6 +337,12 @@ dtb-$(CONFIG_ARCH_QCOM) += sdx75-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb + +shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-evk-imx577-camera.dtbo +shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-evk-imx577-camera.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso new file mode 100644 index 0000000000000..a42a034b92adf --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&camss { + vdd-csiphy-1p2-supply = <&pm4125_l5>; + vdd-csiphy-1p8-supply = <&pm4125_l13>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + csiphy1_ep: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep1>; + }; + }; + }; +}; + +&cci { + status = "okay"; +}; + +&cci_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&mclk1_default>; + pinctrl-names = "default"; + + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + avdd-supply = <&pm4125_l15>; + + port { + imx577_ep1: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; From affd06f23afe4e18615a69afbc689ca1aa784ad6 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 22 May 2026 12:24:57 +0530 Subject: [PATCH 0875/1058] arm64: dts: qcom: shikra-iqs-evk-imx577-camera: Add DT overlay Shikra IQS is an industrial-grade variant using PM8150 PMIC, requiring different CSIPHY and sensor supply rails compared to the retail boards (CQM and CQS) which use PM4125. Add a dedicated overlay for optional IMX577 integration via CSIPHY1. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../qcom/shikra-iqs-evk-imx577-camera.dtso | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index df41830e18edf..2a728c975a38f 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -340,9 +340,11 @@ dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-evk-imx577-camera.dtbo shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-evk-imx577-camera.dtbo +shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-camera.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-imx577-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso new file mode 100644 index 0000000000000..f0423f1ab4e93 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&camss { + vdd-csiphy-1p2-supply = <&pm8150_l11>; + vdd-csiphy-1p8-supply = <&pm8150_l12>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + csiphy1_ep: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep1>; + }; + }; + }; +}; + +&cci { + status = "okay"; +}; + +&cci_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&mclk1_default>; + pinctrl-names = "default"; + + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + dovdd-supply = <&pm8150_l15>; + + port { + imx577_ep1: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; From 554b84e6c1b9b1d6d9e311bc705b540aaaf7b1fc Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 22 May 2026 17:22:05 +0530 Subject: [PATCH 0876/1058] arm64: dts: qcom: shikra: Add CPU OPP tables to scale DDR/L3 Add OPP tables required to scale DDR and L3 per freq-domain on Shikra SoC. Signed-off-by: Sayantan Chakraborty Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 85 ++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 824d4ca0c409e..c0fb8599fa8d7 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -69,6 +69,11 @@ dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; }; cpu1: cpu@100 { @@ -81,6 +86,11 @@ dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; }; cpu2: cpu@200 { @@ -93,6 +103,11 @@ dynamic-power-coefficient = <100>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; }; cpu3: cpu@300 { @@ -105,6 +120,11 @@ dynamic-power-coefficient = <486>; qcom,freq-domain = <&cpufreq_hw 1>; #cooling-cells = <2>; + operating-points-v2 = <&cpu3_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; l2_3: l2-cache { compatible = "cache"; @@ -187,6 +207,71 @@ }; }; + cpu0_opp_table: opp-table-cpu0 { + compatible = "operating-points-v2"; + opp-shared; + + cpu0_opp_768mhz: opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + opp-peak-kBps = <1200000 17817600>; + }; + + cpu0_opp_1017mhz: opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + opp-peak-kBps = <2188000 25804800>; + }; + + cpu0_opp_1094mhz: opp-1094400000 { + opp-hz = /bits/ 64 <1094400000>; + opp-peak-kBps = <3072000 30105600>; + }; + + cpu0_opp_1497mhz: opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <4068000 38707200>; + }; + + cpu0_opp_1612mhz: opp-1612800000 { + opp-hz = /bits/ 64 <1612800000>; + opp-peak-kBps = <6220000 43008000>; + }; + + cpu0_opp_1804mhz: opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; + opp-peak-kBps = <7216000 43622400>; + }; + }; + + cpu3_opp_table: opp-table-cpu3 { + compatible = "operating-points-v2"; + opp-shared; + + cpu3_opp_1017mhz: opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + opp-peak-kBps = <2188000 25804800>; + }; + + cpu3_opp_1190mhz: opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + opp-peak-kBps = <3072000 30105600>; + }; + + cpu3_opp_1497mhz: opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <4068000 38707200>; + }; + + cpu3_opp_1708mhz: opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; + opp-peak-kBps = <6220000 43008000>; + }; + + cpu3_opp_1900mhz: opp-1900800000 { + opp-hz = /bits/ 64 <1900800000>; + opp-peak-kBps = <7216000 43622400>; + }; + }; + pmu { compatible = "arm,armv8-pmuv3"; interrupts = ; From b546476b643dd3ab10aa7b59575b507388ff24bb Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 21 May 2026 17:21:48 +0530 Subject: [PATCH 0877/1058] arm64: dts: qcom: Update cpufreq node for Shikra SoC Update the cpufreq sclaing node compatible as per the latest bindings. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index c0fb8599fa8d7..46965af2fbc16 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -67,6 +67,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; operating-points-v2 = <&cpu0_opp_table>; @@ -84,6 +85,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; operating-points-v2 = <&cpu0_opp_table>; @@ -101,6 +103,7 @@ next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; qcom,freq-domain = <&cpufreq_hw 0>; #cooling-cells = <2>; operating-points-v2 = <&cpu0_opp_table>; @@ -118,6 +121,7 @@ next-level-cache = <&l2_3>; capacity-dmips-mhz = <1946>; dynamic-power-coefficient = <486>; + clocks = <&cpufreq_hw 1>; qcom,freq-domain = <&cpufreq_hw 1>; #cooling-cells = <2>; operating-points-v2 = <&cpu3_opp_table>; @@ -4309,7 +4313,7 @@ }; cpufreq_hw: cpufreq@fd91000 { - compatible = "qcom,shikra-cpufreq-rimps", "qcom,cpufreq-rimps"; + compatible = "qcom,shikra-epss"; reg = <0x0 0x0fd91000 0x0 0x1000>, <0x0 0x0fd92000 0x0 0x1000>; reg-names = "freq-domain0", @@ -4324,6 +4328,7 @@ "dcvsh-irq-1"; #freq-domain-cells = <1>; + #clock-cells = <1>; }; }; From d304eb9d0c5641b3fa95627061e26f98e4eca1dd Mon Sep 17 00:00:00 2001 From: Aditya Sherawat Date: Mon, 27 Apr 2026 13:34:42 +0530 Subject: [PATCH 0878/1058] ARM: dts: msm: Add support for shikra GPU Add the A704 GPU and GMU wrapper device tree nodes to shikra.dtsi, including register mappings, clock, interconnect, IOMMU, OPP table, and zap shader region. Enable the GPU and set the zap shader firmaware path on all three Shikra board variants (cqm-evk, cqs-evk, iqs-evk). Signed-off-by: Aditya Sherawat --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 8 ++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 8 ++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 8 ++ arch/arm64/boot/dts/qcom/shikra.dtsi | 98 +++++++++++++++++++++ 4 files changed, 122 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index a8f6d64ea57df..3bd62ba3221d9 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -39,6 +39,14 @@ }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + &mdss { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index f8d9d4ad81f80..8d87a78bd8782 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -38,6 +38,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + &mdss { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 388b006a854b5..687c978be5bfb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -44,6 +44,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 46965af2fbc16..bc6728eec8994 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1469,6 +1469,104 @@ }; }; + gpu: gpu@5900000 { + compatible = "qcom,adreno-07000400", "qcom,adreno"; + reg = <0x0 0x05900000 0x0 0x40000>, + <0x0 0x0599e000 0x0 0x1000>, + <0x0 0x05961000 0x0 0x800>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem", + "cx_dbgc"; + + interrupts = ; + + clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gcc GCC_DDRSS_GPU_AXI_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>; + clock-names = "core", + "iface", + "mem_iface", + "alt_mem_iface", + "gmu", + "xo"; + + interconnects = <&mem_noc MASTER_GRAPHICS_3D RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "gfx-mem"; + + iommus = <&adreno_smmu 0 1>; + operating-points-v2 = <&gpu_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + qcom,gmu = <&gmu_wrapper>; + + #cooling-cells = <2>; + + status = "disabled"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_micro_code_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-1142400000 { + opp-hz = /bits/ 64 <1142400000>; + required-opps = <&rpmpd_opp_turbo_plus>; + opp-peak-kBps = <8171875>; + }; + + opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + required-opps = <&rpmpd_opp_turbo>; + opp-peak-kBps = <8171875>; + }; + + opp-921600000 { + opp-hz = /bits/ 64 <921600000>; + required-opps = <&rpmpd_opp_nom_plus>; + opp-peak-kBps = <7046875>; + }; + + opp-844800000 { + opp-hz = /bits/ 64 <844800000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <6074218>; + }; + + opp-672000000 { + opp-hz = /bits/ 64 <672000000>; + required-opps = <&rpmpd_opp_svs_plus>; + opp-peak-kBps = <5285156>; + }; + + opp-537600000 { + opp-hz = /bits/ 64 <537600000>; + required-opps = <&rpmpd_opp_svs>; + opp-peak-kBps = <3972656>; + }; + + opp-355200000 { + opp-hz = /bits/ 64 <355200000>; + required-opps = <&rpmpd_opp_low_svs>; + opp-peak-kBps = <2136718>; + }; + }; + }; + + gmu_wrapper: gmu@596a000 { + compatible = "qcom,adreno-gmu-wrapper"; + reg = <0x0 0x0596a000 0x0 0x30000>; + reg-names = "gmu"; + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gpucc GPU_CC_GX_GDSC>; + power-domain-names = "cx", + "gx"; + }; + gpucc: clock-controller@5990000 { compatible = "qcom,shikra-gpucc"; reg = <0x0 0x05990000 0x0 0x9000>; From a9faa40571f57fc8770678b80be5768b9b9599b8 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 25 May 2026 19:04:59 +0530 Subject: [PATCH 0879/1058] arm64: dts: qcom: shikra-iqs-evk: Add DSI panel support Add lcd_bias fixed regulator (3.3V, controlled via pm8150 GPIO4) Enable mdss, mdss_dsi0, mdss_dsi0_phy nodes Add DLC DLC0697 panel node on DSI0 with reset/enable GPIOs, vddio/bias supplies, and TE pin Configure mdss_dsi0_out with 4-lane data path Set pm8150_l11 to 1232mV for DSI VDDA PHY PLL lock Add tlmm pinctrl states for panel reset, reset-suspend, and TE pin. Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 66 +++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 687c978be5bfb..7a2a7b5743bbb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -42,6 +42,18 @@ regulator-max-microvolt = <3300000>; regulator-always-on; }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm8150_l17>; + gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; }; &gpu { @@ -52,6 +64,60 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8150_l11>; + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + enable-gpios = <&pm8150_gpios 1 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm8150_l15>; + bias-supply = <&lcd_bias>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm8150_gpios { + lcd_bias_en: lcd-bias-en-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-disable; + }; +}; + +&pm8150_l11 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; From 6fff4c5a6c63609cd2785b40fde77fa601b18cfa Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Wed, 27 May 2026 23:04:02 +0530 Subject: [PATCH 0880/1058] arm64: dts: qcom: shikra-iqs-evk: Add pinctrl for DLC0697 DSI panel Add TLMM pinctrl states for the DLC0697 DSI panel. This includes configuring GPIO3 for the panel reset signal (active and suspend states) and GPIO86 for the tearing effect (TE) signal using the mdp_vsync_p function. Signed-off-by: Shashank Maurya --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 7a2a7b5743bbb..690601da142e0 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -169,6 +169,29 @@ status = "okay"; }; +&tlmm { + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; +}; + &uart0 { status = "okay"; }; From d86d2cc45c17ea5e4e15740d21c0d840f4fee73f Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Wed, 27 May 2026 18:04:50 +0530 Subject: [PATCH 0881/1058] arm64: dts: qcom: shikra: Add wcn3988-pmu node to EVK boards Add wcn3988-pmu node with supply regulators and bt-enable-gpios to shikra EVK board DTS files. Update the BT node supply references to use PMU-managed LDOs (vreg_pmu_io/xo/rf/ch0) instead of direct PMIC regulators, and move BT node to the board-specific shikra-evk.dtsi. Signed-off-by: Yepuri Siddu --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 36 ++++++++++++++++-- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 37 +++++++++++++++++-- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 9 +++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 41 ++++++++++++++++++--- arch/arm64/boot/dts/qcom/shikra.dtsi | 8 ---- 5 files changed, 109 insertions(+), 22 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 3bd62ba3221d9..170515bb59fab 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -37,6 +37,34 @@ pinctrl-names = "default"; }; + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + + bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + }; + }; }; &gpu { @@ -191,10 +219,10 @@ status = "okay"; bluetooth { - vddio-supply = <&pm4125_l7>; - vddxo-supply = <&pm4125_l13>; - vddrf-supply = <&pm4125_l10>; - vddch0-supply = <&pm4125_l22>; + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 8d87a78bd8782..d59005e56c81b 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -36,6 +36,35 @@ pinctrl-0 = <&lcd_bias_en>; pinctrl-names = "default"; }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + + bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + }; + }; }; &gpu { @@ -189,10 +218,10 @@ status = "okay"; bluetooth { - vddio-supply = <&pm4125_l7>; - vddxo-supply = <&pm4125_l13>; - vddrf-supply = <&pm4125_l10>; - vddch0-supply = <&pm4125_l22>; + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index e69499f77c682..167e15257fcee 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -21,3 +21,12 @@ firmware-name = "qcom/shikra/qupv3fw.elf"; status = "okay"; }; + +&uart8 { + + bluetooth { + compatible = "qcom,wcn3988-bt"; + + max-speed = <3200000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 690601da142e0..f2f1d4ace0332 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -35,9 +35,9 @@ }; }; - vreg_bt_3p3_dummy: regulator-bt-3p3-dummy { + vreg_wcn_3p3: regulator-wcn-3p3 { compatible = "regulator-fixed"; - regulator-name = "bt_3p3_dummy"; + regulator-name = "wcn_3p3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; @@ -54,6 +54,35 @@ pinctrl-0 = <&lcd_bias_en>; pinctrl-names = "default"; }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + vddio-supply = <&pm8150_s4>; + vddxo-supply = <&pm8150_l12>; + vddrf-supply = <&pm8150_l8>; + vddch0-supply = <&vreg_wcn_3p3>; + + bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + }; + }; }; &gpu { @@ -200,10 +229,10 @@ status = "okay"; bluetooth { - vddio-supply = <&pm8150_s4>; - vddxo-supply = <&pm8150_l12>; - vddrf-supply = <&pm8150_l8>; - vddch0-supply = <&vreg_bt_3p3_dummy>; + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index bc6728eec8994..75367b9269004 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2902,14 +2902,6 @@ pinctrl-names = "default"; status = "disabled"; - - bluetooth { - compatible = "qcom,wcn3988-bt"; - - enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; - max-speed = <3200000>; - }; - }; i2c9: i2c@4aa4000 { From 3b0bef79e0528fa5566286a33fc44b3d2718d50d Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 22 May 2026 15:45:07 +0530 Subject: [PATCH 0882/1058] arm64: dts: qcom: shikra: Add gpio-reserved-ranges to tlmm Add gpio-reserved-ranges property to the tlmm node for all three Shikra EVK variants (CQM, CQS, IQS) to mark GPIOs used by the SoC internally and not available for general use. Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 2 ++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 2 ++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 170515bb59fab..9b529e33c3e85 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -181,6 +181,8 @@ }; &tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + lcd_bias_en: lcd-bias-en-state { pins = "gpio151"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index d59005e56c81b..1c931cf2d052a 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -181,6 +181,8 @@ }; &tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + lcd_bias_en: lcd-bias-en-state { pins = "gpio151"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index f2f1d4ace0332..738167d9c0011 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -199,6 +199,8 @@ }; &tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + panel_rst_n: panel-rst-n-state { pins = "gpio3"; function = "gpio"; From e01744f1b9a864c99dd3d7fbb63f6ae5e4ac4213 Mon Sep 17 00:00:00 2001 From: Yepuri Siddu Date: Fri, 29 May 2026 11:43:05 +0530 Subject: [PATCH 0883/1058] arm64: dts: qcom: shikra: Fix wcn3988-pmu node on EVK boards Rename bt-enable-gpios to swctrl-gpios, add sw_ctrl_default pinctrl state for gpio88, and add missing vreg_pmu_ch1 (ldo4) regulator to wcn3988-pmu node across cqm-evk, cqs-evk and iqs-evk boards. Signed-off-by: Yepuri Siddu --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 15 ++++++++++++++- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 16 +++++++++++++++- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 15 ++++++++++++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 9b529e33c3e85..9cc32ae4d5a62 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -40,12 +40,15 @@ wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + vddio-supply = <&pm4125_l7>; vddxo-supply = <&pm4125_l13>; vddrf-supply = <&pm4125_l10>; vddch0-supply = <&pm4125_l22>; - bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; regulators { vreg_pmu_io: ldo0 { @@ -63,6 +66,10 @@ vreg_pmu_ch0: ldo3 { regulator-name = "vreg_pmu_ch0"; }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; }; }; }; @@ -211,6 +218,12 @@ bias-pull-down; }; + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; + }; &uart0 { diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 1c931cf2d052a..6be3dfee7d554 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -40,12 +40,15 @@ wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + vddio-supply = <&pm4125_l7>; vddxo-supply = <&pm4125_l13>; vddrf-supply = <&pm4125_l10>; vddch0-supply = <&pm4125_l22>; - bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; regulators { vreg_pmu_io: ldo0 { @@ -63,6 +66,10 @@ vreg_pmu_ch0: ldo3 { regulator-name = "vreg_pmu_ch0"; }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; }; }; }; @@ -210,6 +217,13 @@ drive-strength = <2>; bias-pull-down; }; + + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; + }; &uart0 { diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 738167d9c0011..5b082eabfc6bc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -58,12 +58,15 @@ wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + vddio-supply = <&pm8150_s4>; vddxo-supply = <&pm8150_l12>; vddrf-supply = <&pm8150_l8>; vddch0-supply = <&vreg_wcn_3p3>; - bt-enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; regulators { vreg_pmu_io: ldo0 { @@ -81,6 +84,10 @@ vreg_pmu_ch0: ldo3 { regulator-name = "vreg_pmu_ch0"; }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; }; }; }; @@ -221,6 +228,12 @@ drive-strength = <2>; bias-pull-down; }; + + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; }; &uart0 { From 6676c0ffa97cc4f697cf1e849494680e3eedb0a0 Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Fri, 29 May 2026 14:25:45 +0530 Subject: [PATCH 0884/1058] arm64: dts: qcom: shikra: Add GPU cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the GPU does not throttle its speed automatically when it reaches high temperatures. Set up GPU cooling by throttling the GPU speed when reaching 115°C. Signed-off-by: Aastha Pandey --- arch/arm64/boot/dts/qcom/shikra.dtsi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 75367b9269004..9f72157564438 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -4547,6 +4547,7 @@ }; gpuss-thermal { + polling-delay-passive = <10>; thermal-sensors = <&tsens0 6>; trips { @@ -4556,12 +4557,25 @@ type = "hot"; }; - gpuss-critical { + gpuss_alert0: gpuss-alert0 { temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + gpuss-critical { + temperature = <120000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-thermal { From 8eaea9b8811d4b56154f9cf3e6b0a33ea5078ec1 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 28 May 2026 22:09:13 +0530 Subject: [PATCH 0885/1058] Revert "arm64: dts: qcom: shikra-iqs-evk: Add pinctrl for DLC0697 DSI panel" This reverts commit 7aa3e6667b315fae478317d505b75023a51360b6. Shikra-IQS-EVK needs DSI-HDMI in place of DSI Panel. Signed-off-by: Mohit Dsor --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 5b082eabfc6bc..f5435d1727d21 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -208,27 +208,6 @@ &tlmm { gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; - panel_rst_n: panel-rst-n-state { - pins = "gpio3"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - - panel_rst_n_suspend: panel-rst-n-suspend-state { - pins = "gpio3"; - function = "gpio"; - drive-strength = <2>; - bias-pull-down; - }; - - panel_te_pin: panel-te-pin-state { - pins = "gpio86"; - function = "mdp_vsync_p"; - drive-strength = <2>; - bias-pull-down; - }; - sw_ctrl_default: sw-ctrl-default-state { pins = "gpio88"; function = "gpio"; From a9eecc7ad1bca2516b2b1c05036002f624486a38 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 28 May 2026 22:20:21 +0530 Subject: [PATCH 0886/1058] Revert "arm64: dts: qcom: shikra-iqs-evk: Add DSI panel support" This reverts commit 872330a93c804b1c2afede355d49f64a29e91f2d. Shikra-IQS-EVK needs DSI-HDMI in place of DSI Panel. Signed-off-by: Mohit Dsor --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 66 --------------------- 1 file changed, 66 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index f5435d1727d21..a790954a99853 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -43,18 +43,6 @@ regulator-always-on; }; - lcd_bias: regulator-lcd-bias { - compatible = "regulator-fixed"; - regulator-name = "lcd_bias"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&pm8150_l17>; - gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; - enable-active-high; - pinctrl-0 = <&lcd_bias_en>; - pinctrl-names = "default"; - }; - wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; @@ -100,60 +88,6 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; -&mdss { - status = "okay"; -}; - -&mdss_dsi0 { - vdda-supply = <&pm8150_l11>; - status = "okay"; - - panel@0 { - compatible = "dlc,dlc0697"; - reg = <0>; - - reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; - enable-gpios = <&pm8150_gpios 1 GPIO_ACTIVE_HIGH>; - - vddio-supply = <&pm8150_l15>; - bias-supply = <&lcd_bias>; - - pinctrl-0 = <&panel_rst_n &panel_te_pin>; - pinctrl-1 = <&panel_rst_n_suspend>; - pinctrl-names = "default", "sleep"; - - port { - panel_in: endpoint { - remote-endpoint = <&mdss_dsi0_out>; - }; - }; - }; -}; - -&mdss_dsi0_out { - remote-endpoint = <&panel_in>; - data-lanes = <0 1 2 3>; -}; - -&mdss_dsi0_phy { - status = "okay"; -}; - -&pm8150_gpios { - lcd_bias_en: lcd-bias-en-state { - pins = "gpio4"; - function = PMIC_GPIO_FUNC_NORMAL; - bias-disable; - }; -}; - -&pm8150_l11 { - /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ - regulator-min-microvolt = <1232000>; - regulator-max-microvolt = <1232000>; - regulator-allow-set-load; -}; - &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; From e6fe53c71acec5c0b91ed16b13abdfe7221539d7 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 28 May 2026 22:29:08 +0530 Subject: [PATCH 0887/1058] arm64: dts: qcom: shikra: Add lt9611uxd node to IQS EVK board Added lt9611uxd node to iqs evk board and done changes like regulators and gpios needed for it. Signed-off-by: Mohit Dsor --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 105 ++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index a790954a99853..f61e96d36c269 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -8,6 +8,7 @@ #include "shikra-iqs-som.dtsi" #include "shikra-evk.dtsi" #include +#include / { model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; @@ -25,7 +26,30 @@ stdout-path = "serial0:115200n8"; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + regulators { + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm8150_l17>; + gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + vreg_wlan_3p3_dummy: regulator-wlan-3p3-dummy { compatible = "regulator-fixed"; regulator-name = "wlan_3p3_dummy"; @@ -88,6 +112,71 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&i2c4 { + status = "okay"; + + lt9611uxd: lt,lt9611uxd@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_RISING>; + reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + hdmi-gpios = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default"; + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + + }; + + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8150_l11>; + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm8150_gpios { + lcd_bias_en: lcd-bias-en-state { + pins = "gpio4"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -142,6 +231,22 @@ &tlmm { gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + lt9611_irq_pin: lt9611-irq-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-disable; /* push-pull output: chip drives both HIGH and LOW */ + input-enable; + }; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio76"; + function = "gpio"; + drive-strength = <8>; + output-high; + input-disable; + }; + sw_ctrl_default: sw-ctrl-default-state { pins = "gpio88"; function = "gpio"; From fd1f653534e23ff477c8dd9b0678d933258a10b8 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 1 Jun 2026 09:21:59 +0800 Subject: [PATCH 0888/1058] arm64: dts: qcom: shikra: migrate WiFi power control to pwrseq Switch WiFi supply nodes to PMU regulators and move power control from driver to pwrseq, aligning with the Bluetooth power model. Also remove unused dummy WLAN 3.3V regulator. Signed-off-by: Miaoqing Pan --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 6 +++--- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 6 +++--- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 14 +++----------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 9cc32ae4d5a62..e0fab065aea12 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -268,9 +268,9 @@ &wifi { vdd-0.8-cx-mx-supply = <&pm4125_l7>; - vdd-1.8-xo-supply = <&pm4125_l13>; - vdd-1.3-rfa-supply = <&pm4125_l10>; - vdd-3.3-ch0-supply = <&pm4125_l22>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; firmware-name = "cq2390"; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 6be3dfee7d554..c9dea2c921856 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -272,9 +272,9 @@ &wifi { vdd-0.8-cx-mx-supply = <&pm4125_l7>; - vdd-1.8-xo-supply = <&pm4125_l13>; - vdd-1.3-rfa-supply = <&pm4125_l10>; - vdd-3.3-ch0-supply = <&pm4125_l22>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; firmware-name = "cq2390"; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index f61e96d36c269..96fd3f168fa16 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -49,14 +49,6 @@ pinctrl-0 = <&lcd_bias_en>; pinctrl-names = "default"; }; - - vreg_wlan_3p3_dummy: regulator-wlan-3p3-dummy { - compatible = "regulator-fixed"; - regulator-name = "wlan_3p3_dummy"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; }; vreg_wcn_3p3: regulator-wcn-3p3 { @@ -292,9 +284,9 @@ &wifi { vdd-0.8-cx-mx-supply = <&pm8150_s4>; - vdd-1.8-xo-supply = <&pm8150_l12>; - vdd-1.3-rfa-supply = <&pm8150_l8>; - vdd-3.3-ch0-supply = <&vreg_wlan_3p3_dummy>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; firmware-name = "cq2390"; From 12c2d4f014352b3aeba805cbed45a5d80c8fb7c3 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 22 May 2026 18:13:59 +0530 Subject: [PATCH 0889/1058] PENDING: arm64: dts: qcom: shikra: add reboot-mode support Add reboot-mode child nodes to shikra-evk.dtsi to configure fastboot (mode-bootloader) and EDL (mode-edl) reboot modes, since all EVK board DTS files include this shared DTSI. Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 167e15257fcee..99f88fb48e808 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -17,6 +17,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_0 { firmware-name = "qcom/shikra/qupv3fw.elf"; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 9f72157564438..b9e63c154e279 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -281,7 +281,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; }; From 7090abce31a1d40f129ade58642ab15951ca95ba Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 1 Jun 2026 18:37:31 +0530 Subject: [PATCH 0890/1058] arm64: dts: qcom: shikra: Split PMU nodes for heterogeneous CPUs Arm heterogeneous configurations should have separate PMU nodes for each CPU arch as the arch specific events can be different. The "arm,armv8-pmuv3" compatible is also intended for s/w models rather than specific arch implementations. All the kryo CPUs are missing PMU compatibles, so they can't be fixed. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index b9e63c154e279..499c66108c90d 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -276,9 +276,14 @@ }; }; - pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = ; + pmu-a55 { + compatible = "arm,cortex-a55-pmu"; + interrupts = ; + }; + + pmu-a78c { + compatible = "arm,cortex-a78-pmu"; + interrupts = ; }; psci: psci { @@ -2141,6 +2146,16 @@ #address-cells = <2>; #size-cells = <2>; ranges; + + ppi-partitions { + ppi_cluster0: interrupt-partition-0 { + affinity = <&cpu0 &cpu1 &cpu2>; + }; + + ppi_cluster1: interrupt-partition-1 { + affinity = <&cpu3>; + }; + }; }; apcs_glb: mailbox@f400000 { From 6eab298e7bd89e00fffc56074298aab79272868f Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 1 Jun 2026 18:43:47 +0530 Subject: [PATCH 0891/1058] arm64: dts: qcom: shikra: switch to interrupt-cells 4 to add PPI partitions The ARM PMUs share the same per-cpu (PPI) interrupt, so we need to switch to interrupt-cells = <4> in the GIC node to allow adding an interrupt partition map phandle as the 4th cell value for GIC_PPI interrupts. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 368 +++++++++++++-------------- 1 file changed, 184 insertions(+), 184 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 499c66108c90d..8057fce51eee5 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -296,7 +296,7 @@ glink-edge { compatible = "qcom,glink-rpm"; - interrupts = ; + interrupts = ; qcom,rpm-msg-ram = <&rpm_msg_ram>; mboxes = <&apcs_glb 0>; @@ -358,7 +358,7 @@ mpm: interrupt-controller { compatible = "qcom,mpm"; qcom,rpm-msg-ram = <&apss_mpm>; - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 1>; interrupt-controller; #interrupt-cells = <2>; @@ -464,7 +464,7 @@ compatible = "qcom,smp2p"; qcom,smem = <94>, <432>; - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 6>; @@ -487,7 +487,7 @@ compatible = "qcom,smp2p"; qcom,smem = <617>, <616>; - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 10>; @@ -510,7 +510,7 @@ compatible = "qcom,smp2p"; qcom,smem = <435>, <428>; - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 14>; @@ -544,7 +544,7 @@ modem_smsm: modem@1 { reg = <1>; - interrupts = ; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; @@ -574,7 +574,7 @@ compatible = "qcom,shikra-tlmm"; reg = <0x0 0x00500000 0x0 0x700000>; - interrupts = ; + interrupts = ; gpio-controller; #gpio-cells = <2>; @@ -1008,7 +1008,7 @@ compatible = "qcom,shikra-cpu-bwmon", "qcom,sc7280-llcc-bwmon"; reg = <0x0 0x00c91000 0x0 0x1000>; - interrupts = ; + interrupts = ; interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>; @@ -1058,7 +1058,7 @@ <0x0 0x0f00000 0x0 0x80000>, <0x0 0x1000000 0x0 0x80000>; reg-names = "llcc0_base", "llcc1_base", "llcc_broadcast_base"; - interrupts = ; + interrupts = ; }; gcc: clock-controller@1400000 { @@ -1185,7 +1185,7 @@ cryptobam: dma-controller@1b04000 { compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; reg = <0x0 0x01b04000 0x0 0x24000>; - interrupts = ; + interrupts = ; #dma-cells = <1>; iommus = <&apps_smmu 0x84 0x0011>, <&apps_smmu 0x86 0x0011>, @@ -1260,8 +1260,8 @@ compatible = "qcom,shikra-tsens", "qcom,tsens-v2"; reg = <0x0 0x04411000 0x0 0x1000>, <0x0 0x04410000 0x0 0x1000>; - interrupts = , - ; + interrupts = , + ; interrupt-names = "uplow", "critical"; #qcom,sensors = <14>; @@ -1301,8 +1301,8 @@ iommus = <&apps_smmu 0xc0 0x0>; - interrupts = , - ; + interrupts = , + ; interrupt-names = "hc_irq", "pwr_irq"; @@ -1361,8 +1361,8 @@ compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5"; reg = <0x0 0x4784000 0x0 0x1000>; - interrupts = , - ; + interrupts = , + ; interrupt-names = "hc_irq", "pwr_irq"; bus-width = <4>; @@ -1422,10 +1422,10 @@ <&gcc GCC_USB30_PRIM_MASTER_CLK>; assigned-clock-rates = <19200000>, <133333333>; - interrupts-extended = <&intc GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>, - <&intc GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>, - <&intc GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, - <&intc GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>; + interrupts-extended = <&intc GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH 0>; interrupt-names = "dwc_usb3", "pwr_event", "qusb2_phy", @@ -1483,7 +1483,7 @@ "cx_mem", "cx_dbgc"; - interrupts = ; + interrupts = ; clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>, <&gpucc GPU_CC_AHB_CLK>, @@ -1590,15 +1590,15 @@ #iommu-cells = <2>; #global-interrupts = <1>; - interrupts = , - , - , - , - , - , - , - , - ; + interrupts = , + , + , + , + , + , + , + , + ; clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>, <&gcc GCC_GPU_MEMNOC_GFX_CLK>, @@ -1615,7 +1615,7 @@ iris: video-codec@5a00000 { compatible = "qcom,shikra-iris", "qcom,qcm2290-venus"; reg = <0 0x5a00000 0 0x200000>; - interrupts = ; + interrupts = ; power-domains = <&gcc GCC_VENUS_GDSC>, <&gcc GCC_VCODEC0_GDSC>, @@ -1726,14 +1726,14 @@ "vfe1", "vfe1_cphy_rx"; - interrupts = , - , - , - , - , - , - , - ; + interrupts = , + , + , + , + , + , + , + ; interrupt-names = "csid0", "csid1", "csiphy0", @@ -1777,7 +1777,7 @@ compatible = "qcom,shikra-cci", "qcom,msm8996-cci"; reg = <0x0 0x05c1b000 0x0 0x1000>; - interrupts = ; + interrupts = ; power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, <&gcc GCC_CAMSS_CCI_0_CLK>; @@ -1812,7 +1812,7 @@ compatible = "qcom,shikra-mdss"; reg = <0x0 0x05e00000 0x0 0x1000>; reg-names = "mdss"; - interrupts = ; + interrupts = ; interrupt-controller; #interrupt-cells = <1>; @@ -2040,71 +2040,71 @@ #iommu-cells = <2>; #global-interrupts = <1>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; }; wifi: wifi@c800000 { @@ -2112,18 +2112,18 @@ reg = <0x0 0x0c800000 0x0 0x800000>; reg-names = "membase"; memory-region = <&wlan_mem>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - ; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; iommus = <&apps_smmu 0x1a0 0x1>; qcom,msa-fixed-perm; @@ -2135,9 +2135,9 @@ reg = <0x0 0xf200000 0x0 0x10000>, /* GICD */ <0x0 0xf240000 0x0 0x80000>; /* GICR * 4 regions */ - interrupts = ; + interrupts = ; - #interrupt-cells = <3>; + #interrupt-cells = <4>; interrupt-controller; #redistributor-regions = <1>; @@ -2167,8 +2167,8 @@ watchdog@f410000 { compatible = "qcom,apss-wdt-shikra", "qcom,kpss-wdt"; reg = <0x0 0x0f410000 0x0 0x1000>; - interrupts = , - ; + interrupts = , + ; clocks = <&sleep_clk>; }; @@ -2184,49 +2184,49 @@ reg = <0x0f421000 0x1000>, <0x0f422000 0x1000>; frame-number = <0>; - interrupts = , - ; + interrupts = , + ; }; frame@f423000 { reg = <0x0f423000 0x1000>; frame-number = <1>; - interrupts = ; + interrupts = ; status = "disabled"; }; frame@f425000 { reg = <0x0f425000 0x1000>; frame-number = <2>; - interrupts = ; + interrupts = ; status = "disabled"; }; frame@f427000 { reg = <0x0f427000 0x1000>; frame-number = <3>; - interrupts = ; + interrupts = ; status = "disabled"; }; frame@f429000 { reg = <0x0f429000 0x1000>; frame-number = <4>; - interrupts = ; + interrupts = ; status = "disabled"; }; frame@f42b000 { reg = <0x0f42b000 0x1000>; frame-number = <5>; - interrupts = ; + interrupts = ; status = "disabled"; }; frame@f42d000 { reg = <0x0f42d000 0x1000>; frame-number = <6>; - interrupts = ; + interrupts = ; status = "disabled"; }; }; @@ -2235,22 +2235,22 @@ compatible = "qcom,shikra-gpi-dma", "qcom,sm6350-gpi-dma"; reg = <0x0 0x04a00000 0x0 0x60000>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; dma-channels = <16>; dma-channel-mask = <0xff>; @@ -2291,7 +2291,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a80000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; @@ -2323,7 +2323,7 @@ compatible = "qcom,geni-spi"; reg = <0x0 0x4a80000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; @@ -2352,7 +2352,7 @@ compatible = "qcom,geni-debug-uart"; reg = <0x0 0x04a80000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; @@ -2374,7 +2374,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a84000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; clock-names = "se"; @@ -2406,7 +2406,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a84000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; clock-names = "se"; @@ -2428,7 +2428,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a88000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; clock-names = "se"; @@ -2460,7 +2460,7 @@ compatible = "qcom,geni-spi"; reg = <0x0 0x4a88000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; clock-names = "se"; @@ -2489,7 +2489,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a88000 0x0 0x4000>; - interrupts-extended = <&intc GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH 0>, <&tlmm 9 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; @@ -2512,7 +2512,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a8c000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; clock-names = "se"; @@ -2544,7 +2544,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a8c000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; clock-names = "se"; @@ -2566,7 +2566,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a90000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; clock-names = "se"; @@ -2598,7 +2598,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a90000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; clock-names = "se"; @@ -2620,7 +2620,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a94000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; clock-names = "se"; @@ -2652,7 +2652,7 @@ compatible = "qcom,geni-spi"; reg = <0x0 0x4a94000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; clock-names = "se"; @@ -2681,7 +2681,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a94000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; clock-names = "se"; @@ -2703,7 +2703,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a98000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; clock-names = "se"; @@ -2735,7 +2735,7 @@ compatible = "qcom,geni-spi"; reg = <0x0 0x4a98000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; clock-names = "se"; @@ -2764,7 +2764,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a98000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; clock-names = "se"; @@ -2786,7 +2786,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4a9c000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; clock-names = "se"; @@ -2818,7 +2818,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04a9c000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; clock-names = "se"; @@ -2840,7 +2840,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4aa0000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; clock-names = "se"; @@ -2872,7 +2872,7 @@ compatible = "qcom,geni-spi"; reg = <0x0 0x4aa0000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; clock-names = "se"; @@ -2901,7 +2901,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04aa0000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; clock-names = "se"; @@ -2923,7 +2923,7 @@ compatible = "qcom,geni-i2c"; reg = <0x0 0x4aa4000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; clock-names = "se"; @@ -2955,7 +2955,7 @@ compatible = "qcom,geni-uart"; reg = <0x0 0x04aa4000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; clock-names = "se"; @@ -2977,7 +2977,7 @@ bam_dmux_dma: dma-controller@6044000 { compatible = "qcom,bam-v1.7.0"; reg = <0x0 0x06044000 0x0 0x19000>; - interrupts = ; + interrupts = ; #dma-cells = <1>; qcom,ee = <0>; @@ -2990,7 +2990,7 @@ compatible = "qcom,shikra-mpss-pas"; reg = <0x0 0x06080000 0x0 0x100>; - interrupts-extended = <&intc GIC_SPI 307 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&intc GIC_SPI 307 IRQ_TYPE_EDGE_RISING 0>, <&modem_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, <&modem_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, <&modem_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, @@ -3021,7 +3021,7 @@ status = "disabled"; glink-edge { - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 12>; qcom,remote-pid = <1>; label = "mpss"; @@ -4287,7 +4287,7 @@ compatible = "qcom,shikra-cdsp-pas"; reg = <0x0 0x0b300000 0x0 0x100000>; - interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING 0>, <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, @@ -4318,7 +4318,7 @@ status = "disabled"; glink-edge { - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 4>; qcom,remote-pid = <5>; label = "cdsp"; @@ -4379,7 +4379,7 @@ compatible = "qcom,shikra-lpaicp-pas"; reg = <0x0 0x0b800000 0x0 0x200000>; - interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING 0>, <&lmcu_smp2p_in 0 IRQ_TYPE_NONE>, <&lmcu_smp2p_in 1 IRQ_TYPE_NONE>, <&lmcu_smp2p_in 2 IRQ_TYPE_NONE>, @@ -4402,7 +4402,7 @@ status = "disabled"; glink-edge { - interrupts = ; + interrupts = ; mboxes = <&apcs_glb 9>; qcom,remote-pid = <26>; label = "lpaicp"; @@ -4427,8 +4427,8 @@ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; clock-names = "xo", "alternate"; - interrupts = , - ; + interrupts = , + ; interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1"; @@ -4723,9 +4723,9 @@ timer { compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; + interrupts = , + , + , + ; }; }; From b88f4560d115c3111ff96c8713962839846c6b35 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:30:35 +0530 Subject: [PATCH 0892/1058] arm64: dts: qcom: shikra: add cache sizes and fix cpu3 power coefficient Add cache-size properties to the L2 cache for cpu3 (256 KiB) and the shared L3 cache (512 KiB) to allow the kernel to correctly report cache topology. Also correct the dynamic-power-coefficient for cpu3 from 486 to 489 to reflect the accurate power model for that CPU cluster. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 8057fce51eee5..3f2d249e19c3b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -120,7 +120,7 @@ enable-method = "psci"; next-level-cache = <&l2_3>; capacity-dmips-mhz = <1946>; - dynamic-power-coefficient = <486>; + dynamic-power-coefficient = <489>; clocks = <&cpufreq_hw 1>; qcom,freq-domain = <&cpufreq_hw 1>; #cooling-cells = <2>; @@ -135,6 +135,7 @@ cache-level = <2>; cache-unified; next-level-cache = <&l3>; + cache-size = <0x40000>; }; }; @@ -164,6 +165,7 @@ compatible = "cache"; cache-level = <3>; cache-unified; + cache-size = <0x80000>; }; }; From c32ee6365330539bb57b215267b5ca32e1ee3a38 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:34:56 +0530 Subject: [PATCH 0893/1058] arm64: dts: qcom: shikra: add SCM clock and reset-cells to firmware node The SCM node requires the CE1 clock to be enabled for cryptographic operations. Add the core clock reference and clock-names property to allow the SCM driver to manage it correctly. Also add #reset-cells = <1> to expose the SCM reset controller interface. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 3f2d249e19c3b..502cd2cdc50e6 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -186,7 +186,10 @@ firmware { scm { compatible = "qcom,scm-shikra", "qcom,scm"; + clocks = <&rpmcc RPM_SMD_CE1_CLK>; + clock-names = "core"; qcom,dload-mode = <&tcsr_regs 0x13000>; + #reset-cells = <1>; interconnects = <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; }; From 880c133fc0c9a491a28cdb03a4989e240e1bd903 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:36:13 +0530 Subject: [PATCH 0894/1058] arm64: dts: qcom: shikra: fix memory node base address The reserved-memory list allocates memory regions well below memory node address, such as hyp@80000000 and smem@86000000. Correct the memory node base address from 0xa0000000 to 0x80000000, which is the actual start of DRAM on shikra. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 502cd2cdc50e6..5ab2f0d628cc8 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -195,10 +195,10 @@ }; }; - memory@a0000000 { + memory@80000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ - reg = <0x0 0xa0000000 0x0 0x0>; + reg = <0x0 0x80000000 0x0 0x0>; }; modem-etm0 { From fce8ddf43cc6f7c89ae37fd77824f3b9cbed0257 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:40:10 +0530 Subject: [PATCH 0895/1058] arm64: dts: qcom: shikra: drop unused labels from OPP table entries Remove the per-node labels (e.g. cpu0_opp_768mhz, cpu3_opp_1017mhz) from all OPP entries in cpu0_opp_table and cpu3_opp_table. These labels are not referenced anywhere. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 5ab2f0d628cc8..8ca85d6447b28 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -220,32 +220,32 @@ compatible = "operating-points-v2"; opp-shared; - cpu0_opp_768mhz: opp-768000000 { + opp-768000000 { opp-hz = /bits/ 64 <768000000>; opp-peak-kBps = <1200000 17817600>; }; - cpu0_opp_1017mhz: opp-1017600000 { + opp-1017600000 { opp-hz = /bits/ 64 <1017600000>; opp-peak-kBps = <2188000 25804800>; }; - cpu0_opp_1094mhz: opp-1094400000 { + opp-1094400000 { opp-hz = /bits/ 64 <1094400000>; opp-peak-kBps = <3072000 30105600>; }; - cpu0_opp_1497mhz: opp-1497600000 { + opp-1497600000 { opp-hz = /bits/ 64 <1497600000>; opp-peak-kBps = <4068000 38707200>; }; - cpu0_opp_1612mhz: opp-1612800000 { + opp-1612800000 { opp-hz = /bits/ 64 <1612800000>; opp-peak-kBps = <6220000 43008000>; }; - cpu0_opp_1804mhz: opp-1804800000 { + opp-1804800000 { opp-hz = /bits/ 64 <1804800000>; opp-peak-kBps = <7216000 43622400>; }; @@ -255,27 +255,27 @@ compatible = "operating-points-v2"; opp-shared; - cpu3_opp_1017mhz: opp-1017600000 { + opp-1017600000 { opp-hz = /bits/ 64 <1017600000>; opp-peak-kBps = <2188000 25804800>; }; - cpu3_opp_1190mhz: opp-1190400000 { + opp-1190400000 { opp-hz = /bits/ 64 <1190400000>; opp-peak-kBps = <3072000 30105600>; }; - cpu3_opp_1497mhz: opp-1497600000 { + opp-1497600000 { opp-hz = /bits/ 64 <1497600000>; opp-peak-kBps = <4068000 38707200>; }; - cpu3_opp_1708mhz: opp-1708800000 { + opp-1708800000 { opp-hz = /bits/ 64 <1708800000>; opp-peak-kBps = <6220000 43008000>; }; - cpu3_opp_1900mhz: opp-1900800000 { + opp-1900800000 { opp-hz = /bits/ 64 <1900800000>; opp-peak-kBps = <7216000 43622400>; }; From 162813ed17276e9d201d9193c8bbc60e79d63739 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:44:28 +0530 Subject: [PATCH 0896/1058] arm64: dts: qcom: shikra: fix LLCC interrupt number Correct the LLCC system cache controller interrupt from SPI 571 to SPI 539, which is the correct GIC SPI line for the LLCC on shikra. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 8ca85d6447b28..55a9b3aab4b62 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1062,8 +1062,10 @@ reg = <0x0 0x00e00000 0x0 0x80000>, <0x0 0x0f00000 0x0 0x80000>, <0x0 0x1000000 0x0 0x80000>; - reg-names = "llcc0_base", "llcc1_base", "llcc_broadcast_base"; - interrupts = ; + reg-names = "llcc0_base", + "llcc1_base", + "llcc_broadcast_base"; + interrupts = ; }; gcc: clock-controller@1400000 { From fe2cf69000513f4d20b51e58d971be9fb5bf517c Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:53:18 +0530 Subject: [PATCH 0897/1058] arm64: dts: qcom: shikra: fix qfprom base address and child offsets Correct the qfprom efuse node base address from 0x01b40000 to 0x01b44000 and expand the region size from 0x700 to 0x3000. Update the child fuse offsets accordingly: - hstx-trim: node address and reg corrected to 0x25b - gpu-speed-bin: node address and reg corrected from 0x6006 to 0x2006 Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 55a9b3aab4b62..bd1798e5eff68 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1224,19 +1224,19 @@ interconnect-names = "memory"; }; - qfprom: efuse@1b40000 { + qfprom: efuse@1b44000 { compatible = "qcom,shikra-qfprom", "qcom,qfprom"; - reg = <0x0 0x01b40000 0x0 0x700>; + reg = <0x0 0x01b44000 0x0 0x3000>; #address-cells = <1>; #size-cells = <1>; - qusb2_hstx_trim_1: hstx-trim@258 { + qusb2_hstx_trim_1: hstx-trim@25b { reg = <0x25b 0x1>; bits = <1 4>; }; - gpu_speed_bin: gpu-speed-bin@6006 { - reg = <0x6006 0x2>; + gpu_speed_bin: gpu-speed-bin@2006 { + reg = <0x2006 0x2>; bits = <5 8>; }; }; From be2aade43d00290e6ccb39351eccd0e51b76dfba Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:55:53 +0530 Subject: [PATCH 0898/1058] arm64: dts: qcom: shikra: fix sdhc_1 interconnect tags and power domain Switch the sdhc_1 interconnect path tags from QCOM_ICC_TAG_ALWAYS and QCOM_ICC_TAG_ACTIVE_ONLY to the RPM-specific RPM_ALWAYS_TAG and RPM_ACTIVE_TAG macros, which are the correct tags for RPM-managed interconnects on this platform. Also correct the power domain reference from RPMHPD_CX to RPMPD_VDDCX to match the RPM power domain provider used on shikra. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index bd1798e5eff68..f954cb20b020f 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1320,14 +1320,14 @@ "core", "xo"; - interconnects = <&system_noc MASTER_SDCC_1 QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>, - <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY - &config_noc SLAVE_SDCC_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnects = <&system_noc MASTER_SDCC_1 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_SDCC_1 RPM_ACTIVE_TAG>; interconnect-names = "sdhc-ddr", "cpu-sdhc"; - power-domains = <&rpmpd RPMHPD_CX>; + power-domains = <&rpmpd RPMPD_VDDCX>; operating-points-v2 = <&sdhc1_opp_table>; qcom,dll-config = <0x000f642c>; From 620207811e5b2023d27173a241ff1d46a8ee84d9 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 2 Jun 2026 14:59:17 +0530 Subject: [PATCH 0899/1058] arm64: dts: qcom: shikra: remove spurious crypto interconnect path from remoteprocs Remove the incorrect second interconnect path using MASTER_CRYPTO_CORE0 from both remoteproc_mpss and remoteproc_cdsp nodes. Each remoteproc should only have the single MASTER_AMPSS_M0 to SLAVE_EBI_CH0 path for CPU-to-DDR bandwidth voting. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index f954cb20b020f..e7f6e0be85172 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -3014,8 +3014,6 @@ clock-names = "xo"; interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG - &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, - <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; power-domains = <&rpmpd RPMHPD_CX>; @@ -4311,8 +4309,6 @@ clock-names = "xo"; interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG - &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, - <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; power-domains = <&rpmpd RPMHPD_CX>; From dd57f186597a28dbf300e63b06ef35f5341e4624 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:34 +0530 Subject: [PATCH 0900/1058] arm64: dts: qcom: agatti: Add DSI1 PHY and sleep clocks to DISPCC node Update the DISPCC node on QCM2290 (Agatti) to align with the latest DT bindings changes, which adds support for the DSI1 PHY and sleep clocks. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/agatti.dtsi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index f0b6ae9b81528..f1d93f86d0a62 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -2190,13 +2190,19 @@ <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, - <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>, + <0>, + <0>, + <&sleep_clk>; clock-names = "bi_tcxo", "bi_tcxo_ao", "gcc_disp_gpll0_clk_src", "gcc_disp_gpll0_div_clk_src", "dsi0_phy_pll_out_byteclk", - "dsi0_phy_pll_out_dsiclk"; + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; #power-domain-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; From 6697b2ef345394f2d87392658022a26fb617d7e2 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 25 May 2026 18:08:10 +0530 Subject: [PATCH 0901/1058] arm64: dts: qcom: shikra: Update DISPCC/GPUCC nodes Update DISPCC/GPUCC nodes to re-use Agatti bindings. While at it, update the consumer nodes with the Agatti clock bindings to take care of the compilation issues. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 35 +++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index e7f6e0be85172..47a7e00de8619 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -3,12 +3,12 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include #include #include +#include #include -#include #include -#include #include #include #include @@ -1573,8 +1573,8 @@ compatible = "qcom,adreno-gmu-wrapper"; reg = <0x0 0x0596a000 0x0 0x30000>; reg-names = "gmu"; - power-domains = <&gpucc GPU_CC_CX_GDSC>, - <&gpucc GPU_CC_GX_GDSC>; + power-domains = <&gpucc GPU_CX_GDSC>, + <&gpucc GPU_GX_GDSC>; power-domain-names = "cx", "gx"; }; @@ -1582,9 +1582,11 @@ gpucc: clock-controller@5990000 { compatible = "qcom,shikra-gpucc"; reg = <0x0 0x05990000 0x0 0x9000>; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + clocks = <&gcc GCC_GPU_CFG_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GCC_GPU_GPLL0_CLK_SRC>, <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + power-domains = <&rpmpd RPMPD_VDDCX>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; @@ -1607,7 +1609,7 @@ , ; - clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>, + clocks = <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>, <&gcc GCC_GPU_MEMNOC_GFX_CLK>, <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>, <&gpucc GPU_CC_AHB_CLK>; @@ -1616,7 +1618,7 @@ "iface", "ahb"; - power-domains = <&gpucc GPU_CC_CX_GDSC>; + power-domains = <&gpucc GPU_CX_GDSC>; }; iris: video-codec@5a00000 { @@ -1832,7 +1834,7 @@ resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; - power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>; + power-domains = <&dispcc MDSS_GDSC>; iommus = <&apps_smmu 0x420 0x2>; interconnects = <&mmrt_virt MASTER_MDP_PORT0 RPM_ALWAYS_TAG @@ -2013,15 +2015,26 @@ }; dispcc: clock-controller@5f00000 { - compatible = "qcom,shikra-dispcc"; + compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc"; reg = <0x0 0x05f00000 0x0 0x20000>; clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, - <&sleep_clk>, + <&rpmcc RPM_SMD_XO_A_CLK_SRC>, + <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>, <0>, - <0>; + <0>, + <&sleep_clk>; + clock-names = "bi_tcxo", + "bi_tcxo_ao", + "gcc_disp_gpll0_clk_src", + "gcc_disp_gpll0_div_clk_src", + "dsi0_phy_pll_out_byteclk", + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From a4e928cb68f636db3a7f131ebfd93e59b6b8ba4b Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Wed, 3 Jun 2026 16:29:39 +0530 Subject: [PATCH 0902/1058] arm64: dts: qcom: shikra: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in shikra. Set up CDSP cooling for both instances by throttling the cdsp, when it reaches 115°C. Signed-off-by: Aastha Pandey --- arch/arm64/boot/dts/qcom/shikra.dtsi | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 47a7e00de8619..ffda1685cd3f8 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -4389,6 +4389,14 @@ }; }; }; + + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + cdsp_sw: cdsp_sw { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; }; remoteproc_lpaicp: remoteproc@b800000 { @@ -4619,12 +4627,26 @@ type = "hot"; }; - nsp-critical { + nsp_0_alert0: trip-point1 { temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + nsp-critical { + temperature = <118000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_alert0>; + cooling-device = <&cdsp_sw + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss0-thermal { From cc145122f6efb27c0308b9b48e3b739c3c79e62f Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 14:18:57 +0530 Subject: [PATCH 0903/1058] arm64: dts: qcom: shikra: Add QAIF cpu device Add QAIF cpu device for audio. Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index ffda1685cd3f8..3c4754c8d79f1 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2040,6 +2040,54 @@ #power-domain-cells = <1>; }; + qaif_cpu: audio@a000000 { + compatible = "qcom,shikra-qaif-cpu"; + reg = <0x0 0x0a000000 0x0 0x20000>; + reg-names = "audio-qaif-core"; + + interrupts = ; + interrupt-names = "qaif-irq-audio-core"; + + clocks = <&gcc GCC_LPASS_CONFIG_CLK>, + <&gcc GCC_LPASS_CORE_AXIM_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK>; + clock-names = "gcc_lpass_config_clk", + "gcc_lpass_core_axim_clk", + "audio_core_cc_aud_dma_clk", + "audio_core_cc_aud_dma_mem_clk", + "audio_core_cc_bus_clk", + "audio_core_cc_aif_if0_ebit_clk", + "audio_core_cc_aif_if0_ibit_clk", + "audio_core_cc_aif_if1_ebit_clk", + "audio_core_cc_aif_if1_ibit_clk", + "audio_core_cc_aif_if2_ebit_clk", + "audio_core_cc_aif_if2_ibit_clk", + "audio_core_cc_aif_if3_ebit_clk", + "audio_core_cc_aif_if3_ibit_clk", + "audio_core_cc_ext_mclka_clk", + "audio_core_cc_ext_mclkb_clk"; + + iommus = <&apps_smmu 0x1c0 0x0>; + + #sound-dai-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + sram@c11e000 { compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; reg = <0x0 0x0c11e000 0x0 0x1000>; From 1fee1b566273712a6f340674087c783e7fa22e6c Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 15:06:51 +0530 Subject: [PATCH 0904/1058] arm64: dts: qcom: shikra: Add Audio Soundwire devices for shikra Add Audio Soundwire devices for shikra. unlike other platforms soundwire master connected via VA macro. Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 148 ++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 3c4754c8d79f1..a96bea5875623 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -16,6 +16,7 @@ #include #include #include +#include #include / { @@ -1007,6 +1008,41 @@ drive-strength = <2>; bias-pull-up; }; + + swr_rx_clk: swr-rx-clk { + pins = "gpio107"; + function = "swr0_rx"; + drive-strength = <8>; + bias-disable; + }; + + swr_rx_data0: swr-rx-data0 { + pins = "gpio108"; + function = "swr0_rx"; + drive-strength = <8>; + bias-bus-hold; + }; + + swr_rx_data1: swr-rx-data1 { + pins = "gpio109"; + function = "swr0_rx"; + drive-strength = <8>; + bias-bus-hold; + }; + + swr_tx_clk: swr-tx-clk { + pins = "gpio105"; + function = "swr0_tx"; + drive-strength = <8>; + bias-disable; + }; + + swr_tx_data0: swr-tx-data0 { + pins = "gpio106"; + function = "swr0_tx"; + drive-strength = <8>; + bias-bus-hold; + }; }; pmu@c91000 { @@ -2045,7 +2081,7 @@ reg = <0x0 0x0a000000 0x0 0x20000>; reg-names = "audio-qaif-core"; - interrupts = ; + interrupts = ; interrupt-names = "qaif-irq-audio-core"; clocks = <&gcc GCC_LPASS_CONFIG_CLK>, @@ -2088,6 +2124,116 @@ status = "disabled"; }; + rxmacro: codec@a040000 { + compatible = "qcom,shikra-lpass-rx-macro"; + reg = <0x0 0x0a040000 0x0 0x1000>; + + pinctrl-0 = <&swr_rx_clk>, <&swr_rx_data0>, <&swr_rx_data1>; + pinctrl-names = "default"; + + clocks = <&audiocorecc AUDIO_CORE_CC_RX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_RX_MCLK_2X_CLK>, + <&vamacro>; + clock-names = "mclk", + "npl", + "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + swr0: soundwire@a060000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x0a060000 0x0 0x10000>; + qcom,swr-master-ee-val = <0>; + + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + + label = "RX"; + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + resets = <&audiocorecc AUDIO_CORE_CSR_RX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + + vamacro: codec@a078000 { + compatible = "qcom,shikra-lpass-va-macro"; + reg = <0x0 0x0a078000 0x0 0x2000>; + + pinctrl-0 = <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + clocks = <&audiocorecc AUDIO_CORE_CC_TX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_TX_MCLK_2X_CLK>; + clock-names = "mclk", + "npl"; + + #clock-cells = <0>; + #sound-dai-cells = <1>; + clock-output-names = "fsgen"; + status = "disabled"; + }; + + swr1: soundwire@a080000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x0a080000 0x0 0x10000>; + qcom,swr-master-ee-val = <0>; + + interrupts = , + ; + interrupt-names = "core", "wakeup"; + + clocks = <&vamacro>; + clock-names = "iface"; + + label = "VA_TX"; + + qcom,din-ports = <3>; + qcom,dout-ports = <0>; + + resets = <&audiocorecc AUDIO_CORE_CSR_TX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x01 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x01 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x01 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + sram@c11e000 { compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; reg = <0x0 0x0c11e000 0x0 0x1000>; From 7b405aadc73c0ed2f2fadb7e6a16c4d2f89ca94e Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 14:59:06 +0530 Subject: [PATCH 0905/1058] arm64: dts: qcom: shikra-cqm-evk: Enable sound card on shikra-cqm-evk Enable sound card on shikra-cqm-evk. Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 258 ++++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index e0fab065aea12..61ec4b8a18cfc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -8,6 +8,7 @@ #include "shikra-cqm-som.dtsi" #include "shikra-evk.dtsi" #include +#include / { model = "Qualcomm Technologies, Inc. Shikra CQM EVK"; @@ -37,6 +38,96 @@ pinctrl-names = "default"; }; + mi2s_tdm_sen: mi2s-tdm-sen-qaif-aif { + qcom,qaif-aif-bits-per-lane = <2>; + qcom,qaif-aif-ctrl-data-oe = <1>; + qcom,qaif-aif-full-cycle-en = <0>; + qcom,qaif-aif-invert-sync = <0>; + qcom,qaif-aif-lane-config = <1 1>, <1 0>; + qcom,qaif-aif-loopback-en = <0>; + qcom,qaif-aif-mono-mode-tx = <0>; + qcom,qaif-aif-mono-mode-rx = <0>; + qcom,qaif-aif-sample-width-rx = <16>; + qcom,qaif-aif-sample-width-tx = <16>; + qcom,qaif-aif-slot-width-rx = <32>; + qcom,qaif-aif-slot-width-tx = <32>; + qcom,qaif-aif-slot-en-rx-mask = <0x3>; + qcom,qaif-aif-slot-en-tx-mask = <0x3>; + qcom,qaif-aif-sync-delay = <1>; + qcom,qaif-aif-sync-mode = <1>; + qcom,qaif-aif-sync-src = <1>; + qcom,qaif-intf-dai-id = <34>; + }; + + sound: sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-cqm-evk"; + + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb", + "VA SWR_MIC0", "ADC2_OUTPUT"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_defualt>; + pinctrl-names = "default"; + + headset-capture-dai-link { + link-name = "Headphones Capture"; + + codec { + sound-dai = <&pmic4125_codec 1>, + <&swr1 0>, + <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_VA_TX1>; + }; + }; + + headset-playback-dai-link { + link-name = "Headphones Playback"; + + codec { + sound-dai = <&pmic4125_codec 0>, + <&swr0 0>, + <&rxmacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_RX0>; + }; + }; + + wsa-speaker-dai-link { + link-name = "WSA Speaker Playback"; + + codec { + sound-dai = <&wsa885x_i2c>; + }; + + cpu { + sound-dai = <&qaif_cpu MI2S_SENARY>; + }; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_VA_TX0>; + }; + }; + }; + wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; @@ -74,6 +165,54 @@ }; }; +&i2c3 { + status = "okay"; + + wsa885x_i2c: wsa885x-i2c-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + + pinctrl-names = "default"; + pinctrl-0 = <&wsa885x_i2c_spkr_sd_n>; + + interrupt-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery_config = <2>; + + wsa885x-init-table = + <0x8470 0x2 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(1) */ + 0x8470 0x0 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(0) */ + 0x8470 0x1 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_EN(1) */ + 0x0004 0x1 /* SMP_AMP_CTRL_STEREO_CMT_GRP_MASK - CMT_GRP_MASK(1) */ + 0x8602 0x60 /* CDC_RX0_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8622 0x60 /* CDC_RX1_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8458 0x79 /* PANDEIRO_DIG_CTRL0_VBAT_THRM_FLT_CTL - VBAT_COEF_SEL */ + 0x810B 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 */ + 0x8111 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 */ + 0x813C 0x08 /* SPK_TOP_COMMON_CTRL4 - override_ctl*/ + 0x8102 0x04 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP*/ + 0x811C 0x29 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.SPK_TOP_LF_CH1_CTRL11.*/ + 0x811D 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_TUNE1 - HIZ_DELAY_PROG*/ + 0x8129 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_TUNE1 - HIZ_DELAY_PROG*/ + 0x811A 0x80 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_CTRL9 */ + 0x8126 0x80 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_CTRL9 */ + 0x8103 0x6 /* PANDEIRO_ANA_TOP_SPK_TOP_COMMON_TUNE1 - GAIN_TUNE */ + 0x80CA 0x85 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_MODE_CTL2 */ + 0x80CB 0xE /* PANDEIRO_ANA_TOP_IVSENSE_ADC_MODE_CTL3 */ + 0x80CC 0xC /* PANDEIRO_ANA_TOP_IVSENSE_ADC_REF_CTL */ + 0x80D0 0x80 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 */ + 0x80BA 0xC0 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.SPK_TOP_SPARE3 */ + 0x841C 0x4E /* PANDEIROI2S.TOP.PANDEIRO_DIG_CTRL */ + 0x8435 0x47 /* PANDEIRO_DIG_CTRL0_PA1_FSM_CTL1 - SILENT_STATE_IVS_EN */ + 0x86CE 0x09 /* PANDEIROI2S.TOP.CDC_CLSH_CDC_CLSH.V1P8_BP_CTL2.BP_CNT */ + 0x8667 0x34 /* CDC_COMPANDER1_CTL7 - AGAIN_DELAY */ + 0x800D 0x08>; /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.PON_CKSK_CTL_0 */ + #sound-dai-cells = <0>; + }; +}; + &gpu { status = "okay"; }; @@ -136,6 +275,11 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&qaif_cpu { + aif-interface = <&mi2s_tdm_sen>; + status = "okay"; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -155,6 +299,10 @@ status = "okay"; }; +&rxmacro { + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -187,9 +335,105 @@ status = "okay"; }; +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 + 500000 500000 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 3>; + }; +}; + &tlmm { gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_defualt: dmic_eldo_en_default { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; /* 8 mA */ + bias-disable; + output-high; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + output-high; + bias-disable; + }; + lcd_bias_en: lcd-bias-en-state { pins = "gpio151"; function = "gpio"; @@ -224,6 +468,12 @@ bias-pull-down; }; + wsa885x_i2c_spkr_sd_n: wsa885x-i2c-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + input-disable; + output-enable; + }; }; &uart0 { @@ -280,3 +530,11 @@ &usb_qmpphy_out { remote-endpoint = <&pm4125_ss_in>; }; + +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + status = "okay"; +}; From d422670a4c341abf7598cf2a5943fe5cb35b886b Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Sat, 6 Jun 2026 13:55:45 +0530 Subject: [PATCH 0906/1058] arm64: dts: qcom: shikra-iqs-evk: add audio machine support Enable the audio machine description on the Shikra IQS EVK board. Add the sound card node, VA-DMIC capture and analog playback/capture links, MAX98091 codec wiring, audio-related pinctrl states, and required LPASS clock references. Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 186 ++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 96fd3f168fa16..b30da67f485ab 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -51,6 +51,75 @@ }; }; + sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-iqs-evk"; + + pinctrl-0 = <&i2s0_clk>, <&i2s0_ws>, <&i2s0_data>, <&ext_mclk2_active>; + pinctrl-names = "default"; + + audio-routing = "IN34", "Headset Mic", + "Headset Mic", "MICBIAS", + "DMICL", "Int Mic", + "Int Mic", "MICBIAS", + "Headphone", "HPL", + "Headphone", "HPR", + "Speaker", "SPKL", + "Speaker", "SPKR", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + codec { + sound-dai = <&vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + pri-i2s-playback-dai-link { + link-name = "Analog Playback"; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + pri-i2s-capture-dai-link { + link-name = "Analog Capture"; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_TX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + vreg_wcn_3p3: regulator-wcn-3p3 { compatible = "regulator-fixed"; regulator-name = "wcn_3p3"; @@ -104,6 +173,25 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&i2c3 { + status = "okay"; + + max98091: audio-codec@10 { + compatible = "maxim,max98091"; + reg = <0x10>; + + pinctrl-0 = <&max98091_default>; + pinctrl-names = "default"; + + interrupts-extended = <&tlmm 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; + assigned-clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + }; +}; + &i2c4 { status = "okay"; @@ -169,6 +257,17 @@ }; }; +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@16 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF0_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -223,6 +322,74 @@ &tlmm { gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_default: dmic-eldo-en-default-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ext_mclk2_active: ext-mclk2-state { + pins = "gpio110"; + function = "ext_mclk"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_clk: i2s0-clk-active-state { + pins = "gpio105"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_data: i2s0-data-active-state { + pins = "gpio107", "gpio108", "gpio109"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_ws: i2s0-ws-active-state { + pins = "gpio106"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + lt9611_irq_pin: lt9611-irq-state { pins = "gpio85"; function = "gpio"; @@ -239,6 +406,12 @@ input-disable; }; + max98091_default: max98091-default-state { + pins = "gpio28"; + function = "gpio"; + bias-pull-up; + }; + sw_ctrl_default: sw-ctrl-default-state { pins = "gpio88"; function = "gpio"; @@ -282,6 +455,19 @@ status = "okay"; }; +&vamacro { + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", "npl"; + + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + + status = "okay"; +}; + &wifi { vdd-0.8-cx-mx-supply = <&pm8150_s4>; vdd-1.8-xo-supply = <&vreg_pmu_xo>; From 7e60bb12e3b1a3acf7aa0280172a266959417319 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 26 May 2026 12:36:18 +0530 Subject: [PATCH 0907/1058] arm64: dts: qcom: shikra-cqs-evk: add audio machine support Enable the audio machine description on the Shikra CQS EVK board. Add the sound card node, VA-DMIC capture and WSA playback links, codec and SoundWire endpoint wiring, audio-related pinctrl states, and required LPASS clock references. Add QAIF LPASS clock ID definitions used by the new Shikra sound card clock references. Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 237 +++++++++++++++++++- 1 file changed, 236 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index c9dea2c921856..8e40e8b6631a7 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -25,6 +25,56 @@ stdout-path = "serial0:115200n8"; }; + sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-cqs-evk"; + qcom,tdm-slots = <2>; + qcom,tdm-slot-width = <32>; + qcom,tdm-codec-slot-mask = <0x03>; + + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF2_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "aud-intf2-ibit"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + audio-routing = "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + codec { + sound-dai = <&vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-playback-dai-link { + link-name = "WSA Playback"; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_TDM_RX_0>; + }; + + codec { + sound-dai = <&wsa885x_i2c>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; lcd_bias: regulator-lcd-bias { compatible = "regulator-fixed"; regulator-name = "lcd_bias"; @@ -74,6 +124,10 @@ }; }; +&audiocorecc { + compatible = "qcom,shikra-cqs-audiocorecc"; +}; + &gpu { status = "okay"; }; @@ -82,6 +136,55 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&i2c3 { + status = "okay"; + + wsa885x_i2c: wsa885x-i2c-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + + pinctrl-names = "default"; + pinctrl-0 = <&wsa885x_i2c_spkr_sd_n>; + + interrupt-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery_config = <2>; + + wsa885x-init-table = + <0x8470 0x2 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(1) */ + 0x8470 0x0 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(0) */ + 0x8470 0x1 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_EN(1) */ + 0x0004 0x1 /* SMP_AMP_CTRL_STEREO_CMT_GRP_MASK - CMT_GRP_MASK(1) */ + 0x8602 0x60 /* CDC_RX0_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8622 0x60 /* CDC_RX1_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8458 0x79 /* PANDEIRO_DIG_CTRL0_VBAT_THRM_FLT_CTL - VBAT_COEF_SEL */ + 0x810B 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 */ + 0x8111 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 */ + 0x813C 0x08 /* SPK_TOP_COMMON_CTRL4 - override_ctl*/ + 0x8102 0x04 /* SPK_TOP_COMMON_CTRL2 - LDO_PROG */ + 0x811C 0x29 /* SPK_TOP_LF_CH1_CTRL11 - PHASE90 */ + 0x811D 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_TUNE1 - HIZ_DELAY_PROG*/ + 0x8129 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_TUNE1 - HIZ_DELAY_PROG*/ + 0x811A 0x80 /* SPK_TOP_LF_CH1_CTRL9 - OCP_CLIP_T_CTRL_EXT */ + 0x8126 0x80 /* SPK_TOP_LF_CH2_CTRL9 - OCP_CLIP_T_CTRL_EXT */ + 0x8103 0x6 /* PANDEIRO_ANA_TOP_SPK_TOP_COMMON_TUNE1 - GAIN_TUNE */ + 0x80CA 0x85 /* IVSENSE_ADC_MODE_CTL2 - SPARE_BITS_0 */ + 0x80CB 0xE /* IVSENSE_ADC_MODE_CTL3 - ADC_VREF_VCTL_I */ + 0x80CC 0xC /* IVSENSE_ADC_REF_CTL - ADC_VREF_VCTL_V */ + 0x80D0 0x80 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 */ + 0x80BA 0xC0 /* SPK_TOP_SPARE3 - force VDDSPK_LV_READY high */ + 0x841C 0x4E /* CDC_CLK_CTL - FSM_INTP_CG_DISABLE */ + 0x8435 0x47 /* PANDEIRO_DIG_CTRL0_PA1_FSM_CTL1 - SILENT_STATE_IVS_EN */ + 0x86CE 0x09 /* PANDEIROI2S.TOP.CDC_CLSH_CDC_CLSH.V1P8_BP_CTL2.BP_CNT */ + 0x8667 0x34 /* CDC_COMPANDER1_CTL7 - AGAIN_DELAY */ + 0x800D 0x08>; /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.PON_CKSK_CTL_0 */ + + #sound-dai-cells = <0>; + }; +}; + &mdss { status = "okay"; }; @@ -155,6 +258,17 @@ status = "okay"; }; +&rxmacro { + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_RX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "fsgen"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -187,9 +301,119 @@ status = "okay"; }; +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 + 500000 500000 500000 + 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5 >; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 2 3 4>; + }; +}; + &tlmm { gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_default: dmic-eldo-en-default-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + bias-disable; + }; + + i2s2_sleep: i2s2-sleep-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <2>; + bias-disable; + }; + + wsa885x_i2c_spkr_sd_n: wsa885x-i2c-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + input-disable; + output-enable; + }; lcd_bias_en: lcd-bias-en-state { pins = "gpio151"; function = "gpio"; @@ -270,6 +494,18 @@ remote-endpoint = <&pm4125_ss_in>; }; +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", "npl"; + + qcom,dmic-sample-rate = <4800000>; + status = "okay"; +}; + &wifi { vdd-0.8-cx-mx-supply = <&pm4125_l7>; vdd-1.8-xo-supply = <&vreg_pmu_xo>; @@ -280,4 +516,3 @@ status = "okay"; }; - From f17e30c1b6740374bb4a1e923ea1bbed75f1e6a2 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 26 May 2026 12:36:18 +0530 Subject: [PATCH 0908/1058] arm64: dts: qcom: shikra: add audio, swr, and gpr support Enable Shikra audio support blocks in the base DTSI. Add audio/SoundWire pinctrl states, modem GPR services for q6apm/q6prm, LPASS dai binding include usage, and related audio wiring required by the board DTS. Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra.dtsi | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index a96bea5875623..e42d07e0dcf2e 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include / { @@ -3237,6 +3239,41 @@ mboxes = <&apcs_glb 12>; qcom,remote-pid = <1>; label = "mpss"; + + gpr { + compatible = "qcom,gpr"; + qcom,glink-channels = "modem_apps"; + qcom,domain = ; + qcom,intents = <200 20>; + #address-cells = <1>; + #size-cells = <0>; + + q6apm: service@1 { + compatible = "qcom,q6apm"; + reg = ; + #sound-dai-cells = <0>; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + qcom,vmid = ; + }; + }; + + q6prm: service@2 { + compatible = "qcom,q6prm"; + reg = ; + + q6prmcc: clock-controller { + compatible = "qcom,q6prm-lpass-clocks"; + #clock-cells = <2>; + }; + }; + }; }; }; From dd2dd19d8ad315161a738883ae59ca42523b88ec Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 8 Jun 2026 18:22:03 +0530 Subject: [PATCH 0909/1058] arm64: dts: qcom: shikra: Update RPMCC node Update Shikra RPMCC node to use the Agatti (QCM2290) RPMCC as fallback compatible. Signed-off-by: Imran Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index e42d07e0dcf2e..134d2694df4fd 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -313,7 +313,7 @@ qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { - compatible = "qcom,rpmcc-shikra", "qcom,rpmcc"; + compatible = "qcom,rpmcc-shikra", "qcom,rpmcc-qcm2290", "qcom,rpmcc"; clocks = <&xo_board>; clock-names = "xo"; #clock-cells = <1>; From 96f8e8d372d0b65e766b4bba5bdc4d13d20cc26c Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 9 Jun 2026 22:44:15 +0530 Subject: [PATCH 0910/1058] ASoC: dt-bindings: qcom,sm8250: document ADSP bypass mode Document qcom,adsp-bypass-mode for Shikra CQM EVK sound cards. The property lets a board request CPU-based audio programming and avoid the DSP-oriented hw_params path when both CPU and DSP audio settings may conflict. Signed-off-by: Mohammad Rafi Shaik Signed-off-by: Pratyush Meduri --- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 15f38622b98b9..776779b7845fd 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -63,6 +63,11 @@ properties: List of phandles pointing to auxiliary devices, such as amplifiers, to be added to the sound card. + qcom,adsp-bypass-mode: + type: boolean + description: + Indicates the platform is configured for ADSP bypass mode. + model: $ref: /schemas/types.yaml#/definitions/string description: User visible long sound card name From 00d90ed430777491c547cb0d760ae61d5eef241e Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 9 Jun 2026 22:44:15 +0530 Subject: [PATCH 0911/1058] arm64: dts: qcom: shikra-cqm-evk: enable ADSP bypass mode Enable qcom,adsp-bypass-mode on the Shikra CQM EVK sound card. This selects the CPU-based audio path for the board and avoids conflicts with DSP-based audio settings during hw_params programming. Signed-off-by: Mohammad Rafi Shaik Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 61ec4b8a18cfc..8266c442789eb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -63,6 +63,7 @@ compatible = "qcom,shikra-sndcard"; model = "shikra-cqm-evk"; + qcom,adsp-bypass-mode; audio-routing = "IN1_HPHL", "HPHL_OUT", "IN2_HPHR", "HPHR_OUT", "AMIC2", "MIC BIAS2", From 6e8914397491b8e1fc834181f9f96b51a53733e1 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 9 Jun 2026 22:44:14 +0530 Subject: [PATCH 0912/1058] arm64: dts: qcom: shikra: configure CQS WSA TDM audio Configure the Shikra CQS EVK WSA playback link for the secondary TDM RX interface used by the external WSA codec. Add the two-slot 32-bit TDM slot configuration on the WSA playback DAI link and describe the SECONDARY_TDM_RX_0 BCLK supplied through q6prmcc. Keep the q6apmbedai address and size cells in the board DTS because the child DAI node is board-specific. Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 8e40e8b6631a7..9eeb7c6ffba80 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -64,10 +64,16 @@ cpu { sound-dai = <&q6apmbedai SECONDARY_TDM_RX_0>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; }; codec { sound-dai = <&wsa885x_i2c>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; }; platform { @@ -239,6 +245,17 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + dai@40 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF2_IBIT + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; From 488d8a6566b1986b03ea1c2d990155649c45632c Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 22 Jun 2026 15:05:58 +0530 Subject: [PATCH 0913/1058] arm64: dts: qcom: shikra: align with upstream devicetree submission Align EVK board files with the latest upstream devicetree submission. Link: https://lore.kernel.org/all/20260608-shikra-dt-m1-v4-10-2114300594a6@oss.qualcomm.com/ Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 6 +----- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 6 +----- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 14 ++++++++++++-- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 6 +----- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 8266c442789eb..c1edbbcfce916 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -477,10 +477,6 @@ }; }; -&uart0 { - status = "okay"; -}; - &uart8 { status = "okay"; @@ -523,7 +519,7 @@ vdd-1.3-rfa-supply = <&vreg_pmu_rf>; vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; + firmware-name = "shikra"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 9eeb7c6ffba80..8e3a2836b91dd 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -467,10 +467,6 @@ }; -&uart0 { - status = "okay"; -}; - &uart8 { status = "okay"; @@ -529,7 +525,7 @@ vdd-1.3-rfa-supply = <&vreg_pmu_rf>; vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; + firmware-name = "shikra"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 99f88fb48e808..bd93e84c14250 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -29,11 +29,21 @@ status = "okay"; }; -&uart8 { +&tlmm { + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; +}; + +&uart0 { + status = "okay"; +}; +&uart8 { bluetooth { compatible = "qcom,wcn3988-bt"; - max-speed = <3200000>; }; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index b30da67f485ab..b1d3296b2faeb 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -419,10 +419,6 @@ }; }; -&uart0 { - status = "okay"; -}; - &uart8 { status = "okay"; @@ -474,7 +470,7 @@ vdd-1.3-rfa-supply = <&vreg_pmu_rf>; vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; + firmware-name = "shikra"; status = "okay"; }; From d7c69d36ad6cebee04777f2aa623db3a84a3945c Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Wed, 17 Jun 2026 22:41:44 +0530 Subject: [PATCH 0914/1058] dt-bindings: sound: qcom,q6apm-dai: Document reserved memory Document the optional reserved memory pool used by platforms where q6apm PCM buffers must be allocated from a predefined carveout instead of from an IOMMU-mapped DMA window. Also document qcom,src-vmid so platforms can describe the VMID that TrustZone tracks as the current owner before qcom_scm_assign_mem() is called. This is needed for S2-only memory that is not initially owned by HLOS. Signed-off-by: Pratyush Meduri --- .../bindings/sound/qcom,q6apm-dai.yaml | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml index 9e5b30d9c6e62..4daa3d26b7ab6 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml @@ -17,12 +17,49 @@ properties: const: qcom,q6apm-dais iommus: + description: + IOMMU mappings for the PCM DMA window. Required on platforms where + audio buffers are HLOS-allocated and mapped through an IOMMU (ADSP/ + LPASS path). Omit on platforms where buffers are allocated from a + reserved memory carveout with no IOMMU mapping. minItems: 1 maxItems: 2 + memory-region: + description: + Optional reserved DMA pool for PCM buffers on platforms where the q6apm + DMA buffer must come from a predefined carveout. + maxItems: 1 + + qcom,src-vmid: + description: + Optional VMID that TrustZone currently tracks as the owner of the PCM + DMA buffer before qcom_scm_assign_mem() is called. When absent the + driver defaults to QCOM_SCM_VMID_HLOS (0x3), which is correct for + normal HLOS-allocated memory. Platforms where the buffer resides in + S2-only memory pre-owned by a non-HLOS VMID (e.g. QCOM_SCM_VMID_LPASS + on the mDSP audio path) must set this so the srcvm argument matches + what TZ tracks, otherwise the SCM call is rejected with -EINVAL. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 31 + + qcom,vmid: + description: + Optional list of destination VMIDs to share PCM DMA buffers with when + SCM memory reassignment is required. For reserved memory regions the + full region is reassigned to this destination VMID list. For non-reserved + DMA buffers, HLOS is also kept as a destination so the CPU retains RW + access. Do not list HLOS here. + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + minimum: 1 + maximum: 31 + minItems: 1 + maxItems: 8 + required: - compatible - - iommus additionalProperties: false @@ -32,3 +69,22 @@ examples: compatible = "qcom,q6apm-dais"; iommus = <&apps_smmu 0x1801 0x0>; }; + - | + /* Reserved-memory mDSP path: no IOMMU, carveout shared with DSP VMIDs */ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + audio_carveout_mem: audio-carveout@86200000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0x0 0x86200000 0x0 0x40000>; + }; + }; + + dais { + compatible = "qcom,q6apm-dais"; + memory-region = <&audio_carveout_mem>; + qcom,vmid = <0xf 0x16>; + }; From 305a6c80e05c8b4544f1b8d0fe0ad5c08efdd147 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Wed, 17 Jun 2026 22:41:44 +0530 Subject: [PATCH 0915/1058] arm64: dts: qcom: shikra: Add q6apm audio carveouts Split the existing audio reserved memory into a shared DMA pool for q6apm and a separate mDSP carveout. Point the q6apm DAI node at the mDSP carveout and share it with the MSS MSA and LPASS VMIDs so the audio path can use the reserved buffer without an IOMMU mapping. Signed-off-by: Pratyush Meduri --- arch/arm64/boot/dts/qcom/shikra.dtsi | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 134d2694df4fd..051fbdf60b844 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -411,8 +411,15 @@ hwlocks = <&tcsr_mutex 3>; }; - audio_heap_mem: audio-heap@86200000 { - reg = <0x0 0x86200000 0x0 0x100000>; + audio_carveout_mem: audio-carveout@86200000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x86200000 0x0 0x40000>; + no-map; + }; + + audio_mdsp_carveout_mem: audio-mdsp-carveout@86240000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x86240000 0x0 0x100000>; no-map; }; @@ -3260,7 +3267,9 @@ q6apmdai: dais { compatible = "qcom,q6apm-dais"; - qcom,vmid = ; + memory-region = <&audio_mdsp_carveout_mem>; + qcom,vmid = ; }; }; From 1aa584a5f3eb0e5db5f628035aa70626a3fba367 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 24 Jun 2026 12:04:40 +0530 Subject: [PATCH 0916/1058] arm64: dts: qcom: shikra: update mpss firmware-name paths for EVK variants Update the remoteproc_mpss firmware-name to use board-variant-specific paths for CQM, CQS and IQS EVK boards. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 2 +- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 2 +- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index c1edbbcfce916..817df3a8c766f 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -295,7 +295,7 @@ }; &remoteproc_mpss { - firmware-name = "qcom/shikra/qdsp6sw.mbn"; + firmware-name = "qcom/shikra/cqm/qdsp6sw.mbn"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 8e3a2836b91dd..f634935195c46 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -270,7 +270,7 @@ }; &remoteproc_mpss { - firmware-name = "qcom/shikra/qdsp6sw.mbn"; + firmware-name = "qcom/shikra/cqs/qdsp6sw.mbn"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index b1d3296b2faeb..f5161d6a4e933 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -282,7 +282,7 @@ }; &remoteproc_mpss { - firmware-name = "qcom/shikra/qdsp6sw.mbn"; + firmware-name = "qcom/shikra/cqs/qdsp6sw.mbn"; status = "okay"; }; From 0345ceb28499fda6b42c648737c6540f74c5fa54 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:02 +0530 Subject: [PATCH 0917/1058] FROMLIST: arm64: dts: qcom: shikra: Add ethernet nodes Add the two Gigabit Ethernet controllers present on Shikra (ethernet0 at 0x5d00000, ethernet1 at 0x5d20000). Both nodes are left disabled; board files supply the PHY, pin-control, and queue configuration. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra.dtsi | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 051fbdf60b844..f6d6c324c81d1 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -574,6 +574,84 @@ dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + ethernet0: ethernet@5d00000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d00000 0x0 0x10000>, + <0x0 0x05d16000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_AHB_CLK>, + <&gcc GCC_EMAC0_PTP_CLK>, + <&gcc GCC_EMAC0_RGMII_CLK>, + <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi", "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC0_GDSC>; + resets = <&gcc GCC_EMAC0_BCR>; + iommus = <&apps_smmu 0x0380 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC0_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ethernet1: ethernet@5d20000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d20000 0x0 0x10000>, + <0x0 0x05d36000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_AHB_CLK>, + <&gcc GCC_EMAC1_PTP_CLK>, + <&gcc GCC_EMAC1_RGMII_CLK>, + <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi", "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC1_GDSC>; + resets = <&gcc GCC_EMAC1_BCR>; + iommus = <&apps_smmu 0x03a0 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC1_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + tcsr_mutex: syscon@340000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x00340000 0x0 0x20000>; From a68c58f51c9eb78eaa5f23a2b0122e88cb744b61 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:03 +0530 Subject: [PATCH 0918/1058] FROMLIST: arm64: dts: qcom: shikra-cqm-evk: Enable ethernet0 Enable the first Gigabit Ethernet controller. Add pin-control for the RGMII and MDIO bus, a gpio-hog to assert the PHY power-enable GPIO at boot, and the board-level ethernet0 overlay with PHY and MTL queue configuration. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 117 ++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 817df3a8c766f..979e115e9001f 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -9,6 +9,7 @@ #include "shikra-evk.dtsi" #include #include +#include / { model = "Qualcomm Technologies, Inc. Shikra CQM EVK"; @@ -166,6 +167,92 @@ }; }; +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + &i2c3 { status = "okay"; @@ -427,6 +514,36 @@ output-high; }; + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <149 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + i2s2_default: i2s2-default-active-state { pins = "gpio100", "gpio101", "gpio102", "gpio103"; function = "i2s2"; From 608d99c678518f50cb215d229f310690eba6daad Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:04 +0530 Subject: [PATCH 0919/1058] FROMLIST: arm64: dts: qcom: shikra-cqs-evk: Enable ethernet0 Enable the first Gigabit Ethernet controller. The board layout is identical to the CQM EVK. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 117 ++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index f634935195c46..fe3ff0683d7bf 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -8,6 +8,7 @@ #include "shikra-cqs-som.dtsi" #include "shikra-evk.dtsi" #include +#include / { model = "Qualcomm Technologies, Inc. Shikra CQS EVK"; @@ -134,6 +135,92 @@ compatible = "qcom,shikra-cqs-audiocorecc"; }; +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + &gpu { status = "okay"; }; @@ -410,6 +497,36 @@ output-high; }; + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <149 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + i2s2_default: i2s2-default-active-state { pins = "gpio100", "gpio101", "gpio102", "gpio103"; function = "i2s2"; From 155f1259ae79ddada937fbb3e31b6ccb0966623b Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:05 +0530 Subject: [PATCH 0920/1058] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Enable both ethernet ports Enable both Gigabit Ethernet controllers. Each port has a dedicated PHY with a gpio-hog to assert the power-enable GPIO at boot, pin-control for the RGMII and MDIO bus, and MTL queue configuration. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 233 ++++++++++++++++++++ 1 file changed, 233 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index f5161d6a4e933..27a110be4e255 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -9,6 +9,7 @@ #include "shikra-evk.dtsi" #include #include +#include / { model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; @@ -165,6 +166,178 @@ }; }; +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&emac0_mtl_rx_setup>; + snps,mtl-tx-config = <&emac0_mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + emac0_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac0_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +ðernet1 { + status = "okay"; + phy-handle = <ðphy1>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet1_defaults>; + + snps,mtl-rx-config = <&emac1_mtl_rx_setup>; + snps,mtl-tx-config = <&emac1_mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + emac1_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac1_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + &gpu { status = "okay"; }; @@ -362,6 +535,66 @@ output-high; }; + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + ethernet1_defaults: ethernet1-defaults-state { + rgmii-rx-pins { + pins = "gpio137", "gpio139", "gpio140", + "gpio141", "gpio142"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio143", "gpio144", "gpio145", + "gpio146", "gpio147", "gpio148"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio149", "gpio150"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <66 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + + emac1_phy_en_hog: emac1-phy-en-hog { + gpio-hog; + gpios = <53 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac1-phy-en"; + }; + ext_mclk2_active: ext-mclk2-state { pins = "gpio110"; function = "ext_mclk"; From 10f6341a9b1fb2cc10dcae12bc152d9a17700d64 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 20 May 2026 17:52:09 +0530 Subject: [PATCH 0921/1058] arm64: dts: qcom: shikra: Add PCIe PHY and controller nodes Shikra supports single PCIe instance with 5GT/s x1 lane. Add PCIe controller and PHY node for this single instance. Signed-off-by: Sushrut Shree Trivedi --- arch/arm64/boot/dts/qcom/shikra.dtsi | 159 +++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index f6d6c324c81d1..4fbad7b6007e2 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1403,6 +1403,165 @@ reg = <0 0x04454000 0 0x1000>; }; + pcie: pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,pcie-shikra"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_SLEEP_CLK>, + <&gcc GCC_PCIE_THROTTLE_CORE_CLK>, + <&gcc GCC_PCIE_THROTTLE_XO_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "sleep", + "throttle_core", + "throttle_xo", + "qmip", + "ddrss", + "tile"; + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + max-link-speed = <2>; + + operating-points-v2 = <&pcie_opp_table>; + + status = "disabled"; + + pcie_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + + pcie_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x01 0x8>; + + phys = <&pcie_phy>; + }; + }; + + pcie_phy: phy@45ee000 { + compatible = "qcom,shikra-qmp-gen2x1-pcie-phy"; + reg = <0x0 0x045ee000 0x0 0x1000>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_CLKREF_EN>, + <&gcc GCC_PCIE_RCHNG_PHY_CLK>, + <&gcc GCC_PCIE_PIPE_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "refgen", + "pipe"; + + resets = <&gcc GCC_PCIE_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_RCHNG_PHY_CLK>; + assigned-clock-rates = <100000000>; + + #clock-cells = <0>; + clock-output-names = "pcie_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; From f56dfd1ad94f8f26e0672fa1419b768b4c62202f Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 20 May 2026 18:00:35 +0530 Subject: [PATCH 0922/1058] arm64: dts: qcom: shikra-cqm-evk: Add TC9563 PCIe switch node for PCIe Add a node for the TC9563 PCIe switch connected to PCIe. The switch has three downstream ports.Two embedded Ethernet devices are present on one of the downstream ports. All the ports present in the node represent the downstream ports and embedded endpoints. Power to the TC9563 is supplied through two LDO regulators, which are on by default and are added as fixed regulators. TC9563 can be configured through I2C. Signed-off-by: Sushrut Shree Trivedi --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 159 ++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 979e115e9001f..01464ef826d98 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -17,6 +17,7 @@ chassis-type = "embedded"; aliases { + i2c3 = &i2c3; mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; @@ -60,6 +61,26 @@ qcom,qaif-intf-dai-id = <34>; }; + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + sound: sound { compatible = "qcom,shikra-sndcard"; model = "shikra-cqm-evk"; @@ -309,6 +330,10 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&i2c3 { + status = "okay"; +}; + &mdss { status = "okay"; }; @@ -355,6 +380,114 @@ status = "okay"; }; +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; @@ -580,12 +713,38 @@ bias-pull-down; }; + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + sw_ctrl_default: sw-ctrl-default-state { pins = "gpio88"; function = "gpio"; bias-pull-down; }; + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; + wsa885x_i2c_spkr_sd_n: wsa885x-i2c-spkr-sd-n-active-state { pins = "gpio2"; function = "gpio"; From 2d92057a20010c1a6367b0a716a93fcea48cb9c0 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 20 May 2026 18:02:33 +0530 Subject: [PATCH 0923/1058] arm64: dts: qcom: shikra-cqs-evk: Add TC9563 PCIe switch node for PCIe Add a node for the TC9563 PCIe switch connected to PCIe. The switch has three downstream ports.Two embedded Ethernet devices are present on one of the downstream ports. All the ports present in the node represent the downstream ports and embedded endpoints. Power to the TC9563 is supplied through two LDO regulators, which are on by default and are added as fixed regulators. TC9563 can be configured through I2C. Signed-off-by: Sushrut Shree Trivedi --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 156 ++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index fe3ff0683d7bf..5ea41a9f8241e 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -16,6 +16,7 @@ chassis-type = "embedded"; aliases { + i2c3 = &i2c3; mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; @@ -82,6 +83,7 @@ }; }; }; + lcd_bias: regulator-lcd-bias { compatible = "regulator-fixed"; regulator-name = "lcd_bias"; @@ -94,6 +96,26 @@ pinctrl-names = "default"; }; + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; @@ -317,6 +339,114 @@ status = "okay"; }; +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; @@ -576,12 +706,38 @@ bias-pull-down; }; + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + sw_ctrl_default: sw-ctrl-default-state { pins = "gpio88"; function = "gpio"; bias-pull-down; }; + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; + }; &uart8 { From c580e06892f6f6b1cadcc9b336fa63bfd2ce7b14 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 20 May 2026 18:05:49 +0530 Subject: [PATCH 0924/1058] arm64: dts: qcom: shikra-iqs-evk: Add TC9563 PCIe switch node for PCIe Add a node for the TC9563 PCIe switch connected to PCIe. The switch has three downstream ports.Two embedded Ethernet devices are present on one of the downstream ports. All the ports present in the node represent the downstream ports and embedded endpoints. Power to the TC9563 is supplied through two LDO regulators, which are on by default and are added as fixed regulators. TC9563 can be configured through I2C. Signed-off-by: Sushrut Shree Trivedi --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 157 ++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 27a110be4e255..bb7af6decffd3 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -17,6 +17,7 @@ chassis-type = "embedded"; aliases { + i2c3 = &i2c3; mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; @@ -129,6 +130,26 @@ regulator-always-on; }; + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + wcn3988-pmu { compatible = "qcom,wcn3988-pmu"; @@ -421,6 +442,114 @@ status = "okay"; }; +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_phy { + vdda-phy-supply = <&pm8150_l12>; + vdda-pll-supply = <&pm8150_l9>; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + &pm8150_gpios { lcd_bias_en: lcd-bias-en-state { pins = "gpio4"; @@ -707,3 +836,31 @@ status = "okay"; }; + +&tlmm { + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; +}; From ea6b14e6e3bc9fda7810e8411b65892994782645 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 29 Jun 2026 15:15:16 +0530 Subject: [PATCH 0925/1058] Revert "arm64: dts: qcom: shikra: Add lt9611uxd node to IQS EVK board" This reverts commit 9896f69f0a1205466ce2703a95a21f53b55968b8. Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 107 -------------------- 1 file changed, 107 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index bb7af6decffd3..dc83ecd4f7693 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -8,7 +8,6 @@ #include "shikra-iqs-som.dtsi" #include "shikra-evk.dtsi" #include -#include #include / { @@ -28,31 +27,6 @@ stdout-path = "serial0:115200n8"; }; - hdmi-connector { - compatible = "hdmi-connector"; - type = "a"; - - port { - hdmi_con: endpoint { - remote-endpoint = <<9611_out>; - }; - }; - }; - - regulators { - lcd_bias: regulator-lcd-bias { - compatible = "regulator-fixed"; - regulator-name = "lcd_bias"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&pm8150_l17>; - gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; - enable-active-high; - pinctrl-0 = <&lcd_bias_en>; - pinctrl-names = "default"; - }; - }; - sound { compatible = "qcom,shikra-sndcard"; model = "shikra-iqs-evk"; @@ -386,62 +360,6 @@ }; }; -&i2c4 { - status = "okay"; - - lt9611uxd: lt,lt9611uxd@41 { - compatible = "lontium,lt9611uxd"; - reg = <0x41>; - interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_RISING>; - reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; - hdmi-gpios = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; - - pinctrl-names = "default"; - pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lt9611_a: endpoint { - remote-endpoint = <&mdss_dsi0_out>; - }; - }; - - port@2 { - reg = <2>; - - lt9611_out: endpoint { - remote-endpoint = <&hdmi_con>; - }; - }; - - }; - - }; -}; - -&mdss { - status = "okay"; -}; - -&mdss_dsi0 { - vdda-supply = <&pm8150_l11>; - status = "okay"; -}; - -&mdss_dsi0_out { - remote-endpoint = <<9611_a>; - data-lanes = <0 1 2 3>; -}; - -&mdss_dsi0_phy { - status = "okay"; -}; - &pcie { wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; @@ -550,15 +468,6 @@ }; }; -&pm8150_gpios { - lcd_bias_en: lcd-bias-en-state { - pins = "gpio4"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; -}; - &q6apmbedai { #address-cells = <1>; #size-cells = <0>; @@ -752,22 +661,6 @@ bias-disable; }; - lt9611_irq_pin: lt9611-irq-state { - pins = "gpio85"; - function = "gpio"; - drive-strength = <2>; - bias-disable; /* push-pull output: chip drives both HIGH and LOW */ - input-enable; - }; - - lt9611_rst_pin: lt9611-rst-state { - pins = "gpio76"; - function = "gpio"; - drive-strength = <8>; - output-high; - input-disable; - }; - max98091_default: max98091-default-state { pins = "gpio28"; function = "gpio"; From b9f551b5cadfa3912ace677d46c212cc3bca3a45 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 29 Jun 2026 15:17:43 +0530 Subject: [PATCH 0926/1058] arm64: dts: qcom: Shikra LT9611UXD support Device tree changes to support lt9611uxd hdmi-dsi driver. Link: https://lore.kernel.org/all/20260627-shikra-dt-changes-v1-5-449a402673d0@oss.qualcomm.com/ Signed-off-by: Mohit Dsor Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 122 ++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index dc83ecd4f7693..7a153f904f081 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -96,6 +96,36 @@ }; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + + vreg_lt9611_vcc: regulator-lt9611-vcc { + compatible = "regulator-fixed"; + regulator-name = "lt9611_vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_reg_en>; + }; + + vreg_lt9611_vdd: regulator-lt9611-vdd { + compatible = "regulator-fixed"; + regulator-name = "lt9611_vdd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + vreg_wcn_3p3: regulator-wcn-3p3 { compatible = "regulator-fixed"; regulator-name = "wcn_3p3"; @@ -479,6 +509,78 @@ }; }; +&i2c4 { + status = "okay"; + + lt9611uxd: lt9611uxd@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + vcc-supply = <&vreg_lt9611_vcc>; + vdd-supply = <&vreg_lt9611_vdd>; + lontium,port-select = <1>; /* PORT_SELECT_B */ + + pinctrl-names = "default"; + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8150_l11>; + status = "okay"; + +}; + +&mdss_dsi0_out { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm8150_gpios { + hdmi_reg_en: hdmi-reg-en-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-disable; + }; +}; + +&pm8150_l11 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -674,6 +776,26 @@ }; }; +&tlmm { + lt9611_irq_pin: lt9611-irq-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio76"; + function = "gpio"; + drive-strength = <8>; + output-high; + }; +}; + +&uart0 { + status = "okay"; +}; + &uart8 { status = "okay"; From fc44c7c98884055f3ebad6a31300941eb00f590f Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 11 Dec 2025 11:41:01 -0800 Subject: [PATCH 0927/1058] FROMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Add Glymur compatible Define a Glymur compatible string for the QMP combo PHY, along with resource requirements. Acked-by: Rob Herring (Arm) Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/all/20251209-linux-next-12825-v8-1-42133596bda0@oss.qualcomm.com/ From 4000dd1d7219e6376d86c6a289c927ae0f753a0f Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 11 Dec 2025 11:47:27 -0800 Subject: [PATCH 0928/1058] FROMLIST: dt-bindings: phy: qcom-m31-eusb2: Add Glymur compatible Add the Glymur compatible to the M31 eUSB2 PHY, and use the SM8750 as the fallback. Signed-off-by: Wesley Cheng Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/all/20251209-linux-next-12825-v8-3-42133596bda0@oss.qualcomm.com/ From d5cd473531e2587ce8eb51d340d060f837cbefb6 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Sat, 20 Dec 2025 12:05:35 +0530 Subject: [PATCH 0929/1058] usb: misc: onboard_usb_hub: Add Genesys Logic GL3590 hub support Add support for the GL3590 4 ports USB3.2 hub. This allows to control its reset pins with a gpio. Signed-off-by: Swati Agarwal --- drivers/usb/misc/onboard_usb_dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/onboard_usb_dev.h b/drivers/usb/misc/onboard_usb_dev.h index 3523f8f8a1496..62d93c9720ca7 100644 --- a/drivers/usb/misc/onboard_usb_dev.h +++ b/drivers/usb/misc/onboard_usb_dev.h @@ -153,7 +153,7 @@ static const struct of_device_id onboard_dev_match[] = { { .compatible = "usb5e3,608", .data = &genesys_gl850g_data, }, { .compatible = "usb5e3,610", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,620", .data = &genesys_gl852g_data, }, - { .compatible = "usb5e3,625", .data = &genesys_gl3590_data, }, + { .compatible = "usb5e3,625", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,626", .data = &genesys_gl852g_data, }, { .compatible = "usbbda,179", .data = &realtek_rtl8188etv_data, }, { .compatible = "usbbda,411", .data = &realtek_rts5411_data, }, From 64555fda5d39c6224951bd65f478ebde6db93dd8 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Sat, 20 Dec 2025 12:05:34 +0530 Subject: [PATCH 0930/1058] dt-bindings: usb: Add binding for Genesys Logic GL3590 hub Add the binding for the USB3.2 Genesys Logic GL3590 hub. Signed-off-by: Swati Agarwal --- .../devicetree/bindings/usb/genesys,gl850g.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml index e8b8c03f87a0e..eb51c35059dc9 100644 --- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml +++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml @@ -87,6 +87,17 @@ allOf: peer-hub: true vdd-supply: true + - if: + properties: + compatible: + contains: + enum: + - usb5e3,625 + then: + properties: + peer-hub: true + vdd-supply: false + unevaluatedProperties: false examples: From fa0ec61b71601790e689b5a2546c8db09e0e4aec Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:22 -0800 Subject: [PATCH 0931/1058] FROMLIST: dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Qualcomm Embedded USB Debugger (EUD) can intercept one or two independent High-Speed UTMI paths, depending on the SoC. Each path is distinct with its own HS-PHY interface, connector/controller wiring, and UTMI routing behavior. The EUD hardware sits between the USB2 PHY and the USB controller on each path. The existing binding models only a single UTMI path and does not provide a way to associate the required High-Speed USB PHY. EUD relies on the HS-PHY on the selected UTMI path for link signalling and correct operation of the hardware. Historically, EUD has worked on platforms that use a single UTMI path because the USB controller maintains ownership of the PHY during enumeration and normal operation. This implicit relationship allowed EUD to function even though the dependency on the PHY was not described in the binding. However, this behavior is not guaranteed by hardware. The current binding description is not sufficient for SoCs that expose two independent UTMI paths, where the PHY association and port wiring must be explicitly described. Introduce per-path eud-path child nodes so each UTMI path can describe its HS-PHY, port connections, and the role‑switching capability of its associated USB port. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-2-elson.serrao@oss.qualcomm.com/ --- .../bindings/soc/qcom/qcom,eud.yaml | 100 +++++++++++++----- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 84218636c0d8d..0507252dbf27e 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -10,8 +10,11 @@ maintainers: - Souradeep Chowdhury description: - This binding is used to describe the Qualcomm Embedded USB Debugger, which is - mini USB-hub implemented on chip to support USB-based debug capabilities. + This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip + mini USB hub that enables USB-based debug capabilities. The EUD block is + positioned between the High-Speed USB PHY and the USB controller, where it + intercepts the UTMI interface to support debug and bypass modes. EUD can be + supported on up to two High-Speed USB ports. properties: compatible: @@ -29,26 +32,62 @@ properties: description: EUD interrupt maxItems: 1 - ports: - $ref: /schemas/graph.yaml#/properties/ports + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +patternProperties: + "^eud-path@[0-1]$": + type: object description: - These ports is to be attached to the endpoint of the DWC3 controller node - and type C connector node. The controller has the "usb-role-switch" - property. + Represents one High-Speed UTMI path that EUD intercepts. This node models + the physical data path intercepted by EUD and provides graph endpoints to + link the USB controller and the external connector associated with this path. properties: - port@0: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the DWC3 controller. + reg: + maxItems: 1 + description: Path number + + phys: + maxItems: 1 + description: High-Speed USB PHY associated with this data path. + + usb-role-switch: + type: boolean + description: + Set this property if the USB port on this path is role switch capable. + In device role, debug mode inserts the EUD hub into the UTMI path. In + host role, the EUD hub is bypassed and UTMI traffic flows directly + between the PHY and the USB controller. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: + These ports are to be attached to the endpoint of the USB controller node + and USB connector node. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB controller. - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the type C connector. + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB connector. + + required: + - reg + - phys + - ports + + additionalProperties: false required: - compatible - reg - - ports additionalProperties: false @@ -58,21 +97,30 @@ examples: compatible = "qcom,sc7280-eud", "qcom,eud"; reg = <0x88e0000 0x2000>, <0x88e2000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + eud-path@0 { + reg = <0>; + phys = <&usb_1_hsphy>; + usb-role-switch; - ports { - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; + }; }; - }; - port@1 { - reg = <1>; - eud_con: endpoint { - remote-endpoint = <&con_eud>; + port@1 { + reg = <1>; + eud_con: endpoint { + remote-endpoint = <&con_eud>; + }; }; }; }; From e9841944f764a4cd6cbb28cbc8b0be75ada20b1f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:23 -0800 Subject: [PATCH 0932/1058] FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection EUD can be mapped to either the primary USB port or the secondary USB port depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs attribute to allow userspace to select which port EUD should operate on and update the ABI documentation. This is needed for systems with dual USB ports where EUD needs to be accessible on either port depending on the system configuration and use case. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-3-elson.serrao@oss.qualcomm.com/ --- Documentation/ABI/testing/sysfs-driver-eud | 16 ++++++++ drivers/usb/misc/qcom_eud.c | 43 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 2bab0db2d2f0f..67223f73ee606 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,3 +7,19 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. + +What: /sys/bus/platform/drivers/qcom_eud/.../port +Date: January 2026 +Contact: Elson Serrao +Description: + Selects which USB port the Embedded USB Debugger (EUD) + is mapped to on platforms providing multiple High-Speed + USB ports. + + Valid values: + 0 - Primary USB port + 1 - Secondary USB port + + The attribute is writable only while EUD is disabled. + Reading the attribute returns the currently selected + USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 926419ca560fc..1a136f8f1ae52 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,8 +23,11 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 +#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 +#define EUD_MAX_PORTS 2 + #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -40,6 +43,7 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; + u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -104,8 +108,47 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); +static ssize_t port_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", chip->port_idx); +} + +static ssize_t port_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + u8 port; + int ret; + + ret = kstrtou8(buf, 0, &port); + if (ret) + return ret; + + /* Only port 0 and port 1 are valid */ + if (port >= EUD_MAX_PORTS) + return -EINVAL; + + /* Port selection must be done before enabling EUD */ + if (chip->enabled) { + dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); + return -EBUSY; + } + + writel(port, chip->base + EUD_REG_PORT_SEL); + chip->port_idx = port; + + return count; +} + +static DEVICE_ATTR_RW(port); + static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, + &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 0bcfcd54000d5629775984065b8841a40c835024 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:24 -0800 Subject: [PATCH 0933/1058] FROMLIST: usb: misc: qcom_eud: add per-path High-Speed PHY control EUD hardware can support multiple High-Speed USB paths, each routed through its own PHY. The active path is selected in hardware via the EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the High-Speed PHY associated with the active UTMI path. To support this multi-path capability, the driver must manage PHY resources on a per-path basis, ensuring that the PHY for the currently selected path is properly initialized and powered. This patch restructures the driver to implement per-path PHY management. The driver now powers the appropriate PHY based on the selected and enabled UTMI path, ensuring correct operation when EUD is enabled. Supporting this requires describing the available UTMI paths and their corresponding PHYs in Device Tree. This updates DT requirements and is not backward compatible with older DTs that lacked this description. Historically, EUD appeared to work on single-path systems because the USB controller kept the PHY initialized. However, EUD is designed to operate independently of the USB controller and therefore requires explicit PHY control. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-4-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 130 +++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 1a136f8f1ae52..5cebb64f4a672 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -34,26 +35,96 @@ #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) +struct eud_path { + struct eud_chip *chip; + struct phy *phy; + u8 num; +}; + struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; void __iomem *base; + struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; + bool phy_enabled; u8 port_idx; }; +static int eud_phy_enable(struct eud_chip *chip) +{ + struct eud_path *path; + struct phy *phy; + int ret; + + if (chip->phy_enabled) + return 0; + + path = chip->paths[chip->port_idx]; + if (!path || !path->phy) { + dev_err(chip->dev, "No PHY configured for port %u\n", chip->port_idx); + return -ENODEV; + } + + phy = path->phy; + + ret = phy_init(phy); + if (ret) { + dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + return ret; + } + + ret = phy_power_on(phy); + if (ret) { + dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + phy_exit(phy); + return ret; + } + + chip->phy_enabled = true; + + return 0; +} + +static void eud_phy_disable(struct eud_chip *chip) +{ + struct eud_path *path; + struct phy *phy; + + if (!chip->phy_enabled) + return; + + path = chip->paths[chip->port_idx]; + if (!path || !path->phy) + return; + + phy = path->phy; + + phy_power_off(phy); + phy_exit(phy); + chip->phy_enabled = false; +} + static int enable_eud(struct eud_chip *priv) { int ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + ret = eud_phy_enable(priv); if (ret) return ret; + ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + if (ret) { + eud_phy_disable(priv); + return ret; + } + writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); @@ -70,6 +141,8 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); + eud_phy_disable(priv); + return 0; } @@ -132,6 +205,12 @@ static ssize_t port_store(struct device *dev, if (port >= EUD_MAX_PORTS) return -EINVAL; + /* Check if the corresponding path is available */ + if (!chip->paths[port]) { + dev_err(chip->dev, "EUD not supported on selected port\n"); + return -EOPNOTSUPP; + } + /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -231,8 +310,45 @@ static void eud_role_switch_release(void *data) usb_role_switch_put(chip->role_sw); } +static int eud_init_path(struct eud_chip *chip, struct device_node *np) +{ + struct eud_path *path; + u32 path_num; + int ret; + + ret = of_property_read_u32(np, "reg", &path_num); + if (ret) { + dev_err(chip->dev, "Missing 'reg' property in path node\n"); + return ret; + } + + if (path_num >= EUD_MAX_PORTS) { + dev_err(chip->dev, "Invalid path number: %u (max %d)\n", + path_num, EUD_MAX_PORTS - 1); + return -EINVAL; + } + + path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL); + if (!path) + return -ENOMEM; + + path->chip = chip; + path->num = path_num; + + path->phy = devm_of_phy_get(chip->dev, np, NULL); + if (IS_ERR(path->phy)) + return dev_err_probe(chip->dev, PTR_ERR(path->phy), + "Failed to get PHY for path %d\n", path_num); + + chip->paths[path_num] = path; + + return 0; +} + static int eud_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; + struct device_node *child; struct eud_chip *chip; struct resource *res; int ret; @@ -252,6 +368,18 @@ static int eud_probe(struct platform_device *pdev) if (ret) return ret; + for_each_child_of_node(np, child) { + ret = eud_init_path(chip, child); + if (ret) { + of_node_put(child); + return ret; + } + } + + /* Primary path is mandatory. Secondary is optional */ + if (!chip->paths[0]) + return -ENODEV; + chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) return PTR_ERR(chip->base); From abdef2fdd8f1ba31c6ed088ca7b077c0f70c8124 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:25 -0800 Subject: [PATCH 0934/1058] FROMLIST: usb: misc: qcom_eud: add per-path role switch support The EUD hardware can support multiple High-Speed USB paths, each connected to different USB controllers. The current implementation uses a single chip-level role switch, which cannot properly handle multi-path configurations where each path needs independent role management. Since EUD is physically present between the USB connector and the controller, it should also relay the role change requests from the connector. Restructure the driver to support per-path role switches and remove the chip-level role switch. Additionally, as EUD need not modify the USB role upon enabling, remove the unnecessary role switch call from enable_eud(). Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-5-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 80 ++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 5cebb64f4a672..a58022f50484f 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,12 +38,15 @@ struct eud_path { struct eud_chip *chip; struct phy *phy; + struct usb_role_switch *controller_sw; + struct usb_role_switch *eud_sw; + enum usb_role curr_role; + char name[16]; u8 num; }; struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; @@ -129,7 +132,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); + return 0; } static int disable_eud(struct eud_chip *priv) @@ -287,15 +290,21 @@ static irqreturn_t handle_eud_irq(int irq, void *data) static irqreturn_t handle_eud_irq_thread(int irq, void *data) { struct eud_chip *chip = data; + struct eud_path *path; int ret; + path = chip->paths[chip->port_idx]; + if (!path || !path->controller_sw) + goto clear_irq; + if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); +clear_irq: /* set and clear vbus_int_clr[0] to clear interrupt */ writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR); writel(0, chip->base + EUD_REG_VBUS_INT_CLR); @@ -303,15 +312,45 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } +static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) +{ + struct eud_path *path = usb_role_switch_get_drvdata(sw); + int ret; + + /* Forward the role request to the USB controller */ + ret = usb_role_switch_set_role(path->controller_sw, role); + if (ret) { + dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", + usb_role_string(role), path->num, ret); + return ret; + } + + path->curr_role = role; + + return 0; +} + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; + int i; - usb_role_switch_put(chip->role_sw); + for (i = 0; i < EUD_MAX_PORTS; i++) { + struct eud_path *path = chip->paths[i]; + + if (!path) + continue; + + if (path->eud_sw) + usb_role_switch_unregister(path->eud_sw); + if (path->controller_sw) + usb_role_switch_put(path->controller_sw); + } } static int eud_init_path(struct eud_chip *chip, struct device_node *np) { + struct usb_role_switch_desc role_sw_desc = {}; struct eud_path *path; u32 path_num; int ret; @@ -342,6 +381,32 @@ static int eud_init_path(struct eud_chip *chip, struct device_node *np) chip->paths[path_num] = path; + path->curr_role = USB_ROLE_NONE; + + if (!of_property_read_bool(np, "usb-role-switch")) + return 0; + + /* Fetch the USB controller's role switch */ + path->controller_sw = fwnode_usb_role_switch_get(of_fwnode_handle(np)); + if (IS_ERR(path->controller_sw)) + return dev_err_probe(chip->dev, PTR_ERR(path->controller_sw), + "Failed to get controller role switch for path %d\n", + path_num); + + /* Create a role switch */ + role_sw_desc.fwnode = of_fwnode_handle(np); + role_sw_desc.set = eud_role_switch_set; + role_sw_desc.driver_data = path; + snprintf(path->name, sizeof(path->name), "eud-path%u", path_num); + role_sw_desc.name = path->name; + + path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc); + if (IS_ERR(path->eud_sw)) { + dev_err(chip->dev, "Failed to register EUD role switch for path %d: %ld\n", + path_num, PTR_ERR(path->eud_sw)); + return PTR_ERR(path->eud_sw); + } + return 0; } @@ -359,11 +424,6 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - chip->role_sw = usb_role_switch_get(&pdev->dev); - if (IS_ERR(chip->role_sw)) - return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), - "failed to get role switch\n"); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From ec8eff01cdd6afd9ce65ab5182ef339ac4b3829f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:26 -0800 Subject: [PATCH 0935/1058] FROMLIST: usb: misc: qcom_eud: improve enable_store API Currently enable_store() allows operations irrespective of the EUD state, which can result in redundant operations. Avoid this by adding duplicate state checks to skip requests when EUD is already in the desired state. Additionally, improve error handling with explicit logging to provide better feedback. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-6-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index a58022f50484f..0ea6491f963ce 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -168,18 +168,27 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; + /* Skip operation if already in desired state */ + if (chip->enabled == enable) + return count; + if (enable) { ret = enable_eud(chip); - if (!ret) - chip->enabled = enable; - else - disable_eud(chip); - + if (ret) { + dev_err(chip->dev, "failed to enable eud\n"); + return ret; + } } else { ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable eud\n"); + return ret; + } } - return ret < 0 ? ret : count; + chip->enabled = enable; + + return count; } static DEVICE_ATTR_RW(enable); From 57951b99e58e541080895a2af4bc418425f275ba Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:27 -0800 Subject: [PATCH 0936/1058] FROMLIST: usb: misc: qcom_eud: add host mode coordination EUD functions by presenting itself as a USB device to the host PC for debugging, making it incompatible in USB host mode configurations. Enabling EUD, when in host mode can also cause the USB controller to misbehave as the EUD hub can only have one upstream facing port. Handle below two scenarios to prevent these conflicts: 1. Prevent user from enabling EUD via sysfs when the USB port is in host mode. 2. Automatically disable EUD when USB port switches to host mode and re-enable it when exiting host mode. This ensures consistent state management without creating conflicts between the EUD debug hub and the USB controller. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-7-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 79 ++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 0ea6491f963ce..3f1cc7ea2a6ae 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -49,12 +49,15 @@ struct eud_chip { struct device *dev; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; + /* serializes EUD control operations */ + struct mutex state_lock; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; + bool eud_disabled_for_host; u8 port_idx; }; @@ -162,32 +165,66 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); + struct eud_path *path; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; + mutex_lock(&chip->state_lock); + /* Skip operation if already in desired state */ - if (chip->enabled == enable) + if (chip->enabled == enable) { + mutex_unlock(&chip->state_lock); return count; + } + + /* + * Handle double-disable scenario: User is disabling EUD that was already + * disabled due to host mode. Since the hardware is already disabled, we + * only need to clear the host-disabled flag to prevent unwanted re-enabling + * when exiting host mode. This respects the user's explicit disable request. + */ + if (!enable && chip->eud_disabled_for_host) { + chip->eud_disabled_for_host = false; + chip->enabled = false; + mutex_unlock(&chip->state_lock); + return count; + } if (enable) { + /* + * EUD functions by presenting itself as a USB device to the host PC for + * debugging, making it incompatible in USB host mode configuration. + * Prevent enabling EUD in this configuration to avoid hardware conflicts. + */ + path = chip->paths[chip->port_idx]; + if (path && path->curr_role == USB_ROLE_HOST) { + dev_err(chip->dev, "EUD not usable in host mode configuration\n"); + mutex_unlock(&chip->state_lock); + return -EBUSY; + } + ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); + mutex_unlock(&chip->state_lock); return ret; } } else { ret = disable_eud(chip); if (ret) { dev_err(chip->dev, "failed to disable eud\n"); + mutex_unlock(&chip->state_lock); return ret; } } chip->enabled = enable; + mutex_unlock(&chip->state_lock); + return count; } @@ -324,18 +361,56 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { struct eud_path *path = usb_role_switch_get_drvdata(sw); + struct eud_chip *chip = path->chip; int ret; + mutex_lock(&chip->state_lock); + + /* + * EUD must be disabled when USB operates in host mode. EUD functions by + * presenting itself as a USB device to the host PC for debugging, making + * it incompatible in host mode configuration. + * + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to maintain user intent. + */ + + /* Only act if EUD is enabled and this is the active path */ + if (chip->enabled && path->num == chip->port_idx) { + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", + ret); + mutex_unlock(&chip->state_lock); + return ret; + } + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) { + dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", + ret); + mutex_unlock(&chip->state_lock); + return ret; + } + chip->eud_disabled_for_host = false; + } + } + /* Forward the role request to the USB controller */ ret = usb_role_switch_set_role(path->controller_sw, role); if (ret) { dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", usb_role_string(role), path->num, ret); + mutex_unlock(&chip->state_lock); return ret; } path->curr_role = role; + mutex_unlock(&chip->state_lock); + return 0; } @@ -433,6 +508,8 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + mutex_init(&chip->state_lock); + ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From f0f7bd212fcb7c8cc2a09b850963fef6535b890f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:28 -0800 Subject: [PATCH 0937/1058] FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling EUD provides virtual USB attach/detach events to simulate cable plug/unplug while maintaining the physical debug connection. However, the current implementation incorrectly sets the USB role to HOST on virtual detach, which doesn't represent the disconnected state. Fix the virtual detach handling by setting the USB role to NONE instead of HOST, correctly representing the disconnected state. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio https://lore.kernel.org/linux-usb/20260126233830.2193816-8-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 3f1cc7ea2a6ae..60f566427abe2 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -343,10 +343,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) if (!path || !path->controller_sw) goto clear_irq; + /* + * EUD virtual attach/detach event handling for low power debugging: + * + * When EUD is enabled in debug mode, the device remains physically + * connected to the PC throughout the debug session, keeping the USB + * controller active. This prevents testing of low power scenarios that + * require USB disconnection. + * + * EUD solves this by providing virtual USB attach/detach events while + * maintaining the physical connection. These events are triggered from + * the Host PC via the enumerated EUD control interface and delivered + * to the EUD driver as interrupts. + * + * These notifications are forwarded to the USB controller through role + * switch framework. + */ if (chip->usb_attached) ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From 03770eb8f8b05756e0689a42a857ead1b3887aa6 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:29 -0800 Subject: [PATCH 0938/1058] FROMLIST: arm64: dts: qcom: kodiak: Align EUD node with binding The EUD node does not match the current binding and maps USB endpoints to the secondary controller. This SoC supports EUD only on the primary High-Speed USB path. The binding also requires a per-path PHY reference. Model the primary UTMI path as a child node with the required PHY and an empty ports graph. Leave endpoint mapping to board DTS files, and remove the secondary mapping and associated ports so the description conforms to the binding. Signed-off-by: Elson Serrao iLink: https://lore.kernel.org/linux-usb/20260126233830.2193816-9-elson.serrao@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 33 +++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..1a616c0375d31 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,12 +4404,6 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; - - port { - usb2_role_switch: endpoint { - remote-endpoint = <&eud_ep>; - }; - }; }; qspi: spi@88dc000 { @@ -4736,16 +4730,29 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; - ports { - #address-cells = <1>; - #size-cells = <0>; + eud0: eud-path@0 { + reg = <0>; + phys = <&usb_1_hsphy>; - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + eud_usb0: endpoint { + }; + }; + + port@1 { + reg = <1>; + eud_con0: endpoint { + }; }; }; }; From 44f0bf8b35553fd3ea2f9cb320d085ddf4cba698 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:30 -0800 Subject: [PATCH 0939/1058] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality On this board, EUD resides on the primary High-Speed USB data path between the connector and the DWC3 controller. Update the device tree connections to correctly map the connector and controller endpoints, and describe role-switch capability on the EUD primary path. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-10-elson.serrao@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..b320d000508a3 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -211,7 +211,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con0>; }; }; @@ -1403,13 +1403,29 @@ }; &usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; + remote-endpoint = <&eud_usb0>; }; &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; +&eud_con0 { + remote-endpoint = <&pmic_glink_hs_in>; +}; + +&eud_usb0 { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&eud { + status = "okay"; +}; + +&eud0 { + usb-role-switch; +}; + &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; From 53091ccc113ade402faa4502afd3ee0b2ad24618 Mon Sep 17 00:00:00 2001 From: Jan Remmet Date: Fri, 23 Jan 2026 15:52:37 +0100 Subject: [PATCH 0940/1058] FROMLIST: usb: typec: hd3ss3220: Enable VBUS based on role state For systems where the ID pin isn't available as gpio use the ATTACHED_STATE register instead to control vbus. >From the datasheet: "This is an additional method to communicate attach other than the ID pin. These bits can be read by the application to determine what was attached." Use this method if id-gpios property is not set, but the connector node has vbus-supply defined. Check regulator state as peripheral and detach can disable vbus. Signed-off-by: Jan Remmet From 0a6686f54058bec2c89ea8047adbd5d5b3af5cb6 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 16 Feb 2026 01:35:33 +0530 Subject: [PATCH 0941/1058] FROMLIST: usb: typec: hd3ss3220: Add wakeup support from system suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HD3SS3220's interrupt is disabled during system suspend, so a USB‑C cable connect/attach event cannot wake the system. This prevents resume from low‑power modes when the port controller is expected to act as a wakeup source. Add wakeup support by: - Initialize the device as wakeup‑capable. - Enable the HD3SS3220 IRQ as a wakeup interrupt. - Add suspend/resume callbacks to enable or disable the IRQ for wakeup depending on the device's wakeup configuration. With this, USB‑C cable insertion correctly wakes the system from suspend. Link: https://lore.kernel.org/all/20260215183325.3836178-2-swati.agarwal@oss.qualcomm.com/ Signed-off-by: Swati Agarwal --- drivers/usb/typec/hd3ss3220.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index 3e39b800e6b5f..b56df9349f89b 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -501,6 +501,11 @@ static int hd3ss3220_probe(struct i2c_client *client) if (hd3ss3220->poll) schedule_delayed_work(&hd3ss3220->output_poll_work, HZ); + if (client->irq && device_property_read_bool(hd3ss3220->dev, "wakeup-source")) { + device_init_wakeup(&client->dev, true); + enable_irq_wake(client->irq); + } + dev_info(&client->dev, "probed revision=0x%x\n", ret); return 0; @@ -525,6 +530,35 @@ static void hd3ss3220_remove(struct i2c_client *client) usb_role_switch_put(hd3ss3220->role_sw); } +static int __maybe_unused hd3ss3220_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(client->irq); + else + disable_irq(client->irq); + + return 0; +} + +static int __maybe_unused hd3ss3220_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(client->irq); + else + enable_irq(client->irq); + + return 0; +} + +static const struct dev_pm_ops hd3ss3220_pm_ops = { + .suspend = hd3ss3220_suspend, + .resume = hd3ss3220_resume, +}; + static const struct of_device_id dev_ids[] = { { .compatible = "ti,hd3ss3220"}, {} @@ -535,6 +569,7 @@ static struct i2c_driver hd3ss3220_driver = { .driver = { .name = "hd3ss3220", .of_match_table = dev_ids, + .pm = &hd3ss3220_pm_ops, }, .probe = hd3ss3220_probe, .remove = hd3ss3220_remove, From c5610d5cb36b9ed719a84233f06ec44ba914a621 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 20 Feb 2026 16:01:25 +0530 Subject: [PATCH 0942/1058] Revert "FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality" This reverts commit e65028c6aae9f531066bdfc487454ed45e0834a9. Issue is observed with this commit e65028c6aae9f531066bdfc487454ed45e0834a9 leading to crash, with following call stack [ 19.706310][ T73] Call trace: [ 19.706312][ T73] usb_role_switch_unregister+0x28/0x70 (P) [ 19.706319][ T73] eud_role_switch_release+0x30/0x78 [qcom_eud] [ 19.884972][ T73] devm_action_release+0x1c/0x30 [ 19.884981][ T73] release_nodes+0x70/0x120 [ 19.884987][ T73] devres_release_all+0x98/0xf0 [ 19.884995][ T73] device_unbind_cleanup+0x20/0x98 [ 19.885000][ T73] really_probe+0x184/0x3f0 [ 19.885005][ T73] __driver_probe_device+0x88/0x190 [ 19.885010][ T73] driver_probe_device+0x44/0x120 [ 19.885015][ T73] __device_attach_driver+0xc4/0x178 [ 19.885020][ T73] bus_for_each_drv+0x90/0xf8 [ 19.885027][ T73] __device_attach+0xa8/0x1d8 [ 19.885032][ T73] device_initial_probe+0x58/0x68 [ 19.885037][ T73] bus_probe_device+0x40/0xb8 [ 19.885041][ T73] deferred_probe_work_func+0xbc/0x128 [ 19.885046][ T73] process_one_work+0x180/0x450 [ 19.885055][ T73] worker_thread+0x26c/0x388 [ 19.885062][ T73] kthread+0x120/0x140 [ 19.885068][ T73] ret_from_fork+0x10/0x20 [ 19.885079][ T73] Code: f9000bf3 aa0003f3 b140041f 54000168 (390c901f) [ 19.885083][ T73] ---[ end trace 0000000000000000 ]--- [ 19.885088][ T73] Kernel panic - not syncing: Oops: Fatal exception [ 19.885091][ T73] SMP: stopping secondary CPUs Revert commit for now. Signed-off-by: Salendarsingh Gaud --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index b320d000508a3..37a3b51323ce5 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -211,7 +211,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&eud_con0>; + remote-endpoint = <&usb_1_dwc3_hs>; }; }; @@ -1403,29 +1403,13 @@ }; &usb_1_dwc3_hs { - remote-endpoint = <&eud_usb0>; + remote-endpoint = <&pmic_glink_hs_in>; }; &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; -&eud_con0 { - remote-endpoint = <&pmic_glink_hs_in>; -}; - -&eud_usb0 { - remote-endpoint = <&usb_1_dwc3_hs>; -}; - -&eud { - status = "okay"; -}; - -&eud0 { - usb-role-switch; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; From dc37b2a5bbba86d9a7578364ba97ee1a2351987c Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 20 Feb 2026 16:02:45 +0530 Subject: [PATCH 0943/1058] Revert "FROMLIST: arm64: dts: qcom: kodiak: Align EUD node with binding" This reverts commit 09ed0b6ddc99b87f0fb3141a9c4d55f015329c5c. Issue is observed with this commit 09ed0b6ddc99b87f0fb3141a9c4d55f015329c5c leading to crash, with following call stack [ 19.706310][ T73] Call trace: [ 19.706312][ T73] usb_role_switch_unregister+0x28/0x70 (P) [ 19.706319][ T73] eud_role_switch_release+0x30/0x78 [qcom_eud] [ 19.884972][ T73] devm_action_release+0x1c/0x30 [ 19.884981][ T73] release_nodes+0x70/0x120 [ 19.884987][ T73] devres_release_all+0x98/0xf0 [ 19.884995][ T73] device_unbind_cleanup+0x20/0x98 [ 19.885000][ T73] really_probe+0x184/0x3f0 [ 19.885005][ T73] __driver_probe_device+0x88/0x190 [ 19.885010][ T73] driver_probe_device+0x44/0x120 [ 19.885015][ T73] __device_attach_driver+0xc4/0x178 [ 19.885020][ T73] bus_for_each_drv+0x90/0xf8 [ 19.885027][ T73] __device_attach+0xa8/0x1d8 [ 19.885032][ T73] device_initial_probe+0x58/0x68 [ 19.885037][ T73] bus_probe_device+0x40/0xb8 [ 19.885041][ T73] deferred_probe_work_func+0xbc/0x128 [ 19.885046][ T73] process_one_work+0x180/0x450 [ 19.885055][ T73] worker_thread+0x26c/0x388 [ 19.885062][ T73] kthread+0x120/0x140 [ 19.885068][ T73] ret_from_fork+0x10/0x20 [ 19.885079][ T73] Code: f9000bf3 aa0003f3 b140041f 54000168 (390c901f) [ 19.885083][ T73] ---[ end trace 0000000000000000 ]--- [ 19.885088][ T73] Kernel panic - not syncing: Oops: Fatal exception [ 19.885091][ T73] SMP: stopping secondary CPUs Revert commit for now. Signed-off-by: Salendarsingh Gaud --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 33 +++++++++++----------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 1a616c0375d31..fa540d8c2615d 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,6 +4404,12 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; + + port { + usb2_role_switch: endpoint { + remote-endpoint = <&eud_ep>; + }; + }; }; qspi: spi@88dc000 { @@ -4730,29 +4736,16 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - eud0: eud-path@0 { - reg = <0>; - phys = <&usb_1_hsphy>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - eud_usb0: endpoint { - }; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; - port@1 { - reg = <1>; - eud_con0: endpoint { - }; + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; }; }; }; From 12418f7456826085ca85faa83b1fd57454a02c7a Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:19:50 -0700 Subject: [PATCH 0944/1058] Revert "FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling" This reverts commit 7104631aca14a5f01ee8f33ebbfda4c2e4047d28. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 60f566427abe2..3f1cc7ea2a6ae 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -343,26 +343,10 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) if (!path || !path->controller_sw) goto clear_irq; - /* - * EUD virtual attach/detach event handling for low power debugging: - * - * When EUD is enabled in debug mode, the device remains physically - * connected to the PC throughout the debug session, keeping the USB - * controller active. This prevents testing of low power scenarios that - * require USB disconnection. - * - * EUD solves this by providing virtual USB attach/detach events while - * maintaining the physical connection. These events are triggered from - * the Host PC via the enumerated EUD control interface and delivered - * to the EUD driver as interrupts. - * - * These notifications are forwarded to the USB controller through role - * switch framework. - */ if (chip->usb_attached) ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From 986d37ad6a0e94046677245451cff48d6d1fdfa3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:20:22 -0700 Subject: [PATCH 0945/1058] Revert "FROMLIST: usb: misc: qcom_eud: add host mode coordination" This reverts commit 583d6fc0f35f15b14ebed9dd244a7ba4bf845496. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 79 +------------------------------------ 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 3f1cc7ea2a6ae..0ea6491f963ce 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -49,15 +49,12 @@ struct eud_chip { struct device *dev; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; - /* serializes EUD control operations */ - struct mutex state_lock; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; - bool eud_disabled_for_host; u8 port_idx; }; @@ -165,66 +162,32 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); - struct eud_path *path; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; - mutex_lock(&chip->state_lock); - /* Skip operation if already in desired state */ - if (chip->enabled == enable) { - mutex_unlock(&chip->state_lock); + if (chip->enabled == enable) return count; - } - - /* - * Handle double-disable scenario: User is disabling EUD that was already - * disabled due to host mode. Since the hardware is already disabled, we - * only need to clear the host-disabled flag to prevent unwanted re-enabling - * when exiting host mode. This respects the user's explicit disable request. - */ - if (!enable && chip->eud_disabled_for_host) { - chip->eud_disabled_for_host = false; - chip->enabled = false; - mutex_unlock(&chip->state_lock); - return count; - } if (enable) { - /* - * EUD functions by presenting itself as a USB device to the host PC for - * debugging, making it incompatible in USB host mode configuration. - * Prevent enabling EUD in this configuration to avoid hardware conflicts. - */ - path = chip->paths[chip->port_idx]; - if (path && path->curr_role == USB_ROLE_HOST) { - dev_err(chip->dev, "EUD not usable in host mode configuration\n"); - mutex_unlock(&chip->state_lock); - return -EBUSY; - } - ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); - mutex_unlock(&chip->state_lock); return ret; } } else { ret = disable_eud(chip); if (ret) { dev_err(chip->dev, "failed to disable eud\n"); - mutex_unlock(&chip->state_lock); return ret; } } chip->enabled = enable; - mutex_unlock(&chip->state_lock); - return count; } @@ -361,56 +324,18 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { struct eud_path *path = usb_role_switch_get_drvdata(sw); - struct eud_chip *chip = path->chip; int ret; - mutex_lock(&chip->state_lock); - - /* - * EUD must be disabled when USB operates in host mode. EUD functions by - * presenting itself as a USB device to the host PC for debugging, making - * it incompatible in host mode configuration. - * - * chip->enabled preserves user's sysfs configuration and is not modified - * during host mode transitions to maintain user intent. - */ - - /* Only act if EUD is enabled and this is the active path */ - if (chip->enabled && path->num == chip->port_idx) { - if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { - ret = disable_eud(chip); - if (ret) { - dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", - ret); - mutex_unlock(&chip->state_lock); - return ret; - } - chip->eud_disabled_for_host = true; - } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { - ret = enable_eud(chip); - if (ret) { - dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", - ret); - mutex_unlock(&chip->state_lock); - return ret; - } - chip->eud_disabled_for_host = false; - } - } - /* Forward the role request to the USB controller */ ret = usb_role_switch_set_role(path->controller_sw, role); if (ret) { dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", usb_role_string(role), path->num, ret); - mutex_unlock(&chip->state_lock); return ret; } path->curr_role = role; - mutex_unlock(&chip->state_lock); - return 0; } @@ -508,8 +433,6 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - mutex_init(&chip->state_lock); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From e5f26633bb188b0172aa81b99a315e1b98eb8bee Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:20:39 -0700 Subject: [PATCH 0946/1058] Revert "FROMLIST: usb: misc: qcom_eud: improve enable_store API" This reverts commit eb5da51b8cba5fc4ed3bd699d2cce066020e3415. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 0ea6491f963ce..a58022f50484f 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -168,27 +168,18 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; - /* Skip operation if already in desired state */ - if (chip->enabled == enable) - return count; - if (enable) { ret = enable_eud(chip); - if (ret) { - dev_err(chip->dev, "failed to enable eud\n"); - return ret; - } + if (!ret) + chip->enabled = enable; + else + disable_eud(chip); + } else { ret = disable_eud(chip); - if (ret) { - dev_err(chip->dev, "failed to disable eud\n"); - return ret; - } } - chip->enabled = enable; - - return count; + return ret < 0 ? ret : count; } static DEVICE_ATTR_RW(enable); From 7b1b29fa7cac6cda53361c72d36051ce4056a9a3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:03 -0700 Subject: [PATCH 0947/1058] Revert "FROMLIST: usb: misc: qcom_eud: add per-path role switch support" This reverts commit e7e656c813d8d651e26704a10f9c56a34a2f7e13. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 80 +++++-------------------------------- 1 file changed, 10 insertions(+), 70 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index a58022f50484f..5cebb64f4a672 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,15 +38,12 @@ struct eud_path { struct eud_chip *chip; struct phy *phy; - struct usb_role_switch *controller_sw; - struct usb_role_switch *eud_sw; - enum usb_role curr_role; - char name[16]; u8 num; }; struct eud_chip { struct device *dev; + struct usb_role_switch *role_sw; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; @@ -132,7 +129,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return 0; + return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); } static int disable_eud(struct eud_chip *priv) @@ -290,21 +287,15 @@ static irqreturn_t handle_eud_irq(int irq, void *data) static irqreturn_t handle_eud_irq_thread(int irq, void *data) { struct eud_chip *chip = data; - struct eud_path *path; int ret; - path = chip->paths[chip->port_idx]; - if (!path || !path->controller_sw) - goto clear_irq; - if (chip->usb_attached) - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); -clear_irq: /* set and clear vbus_int_clr[0] to clear interrupt */ writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR); writel(0, chip->base + EUD_REG_VBUS_INT_CLR); @@ -312,45 +303,15 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) -{ - struct eud_path *path = usb_role_switch_get_drvdata(sw); - int ret; - - /* Forward the role request to the USB controller */ - ret = usb_role_switch_set_role(path->controller_sw, role); - if (ret) { - dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", - usb_role_string(role), path->num, ret); - return ret; - } - - path->curr_role = role; - - return 0; -} - static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; - int i; - for (i = 0; i < EUD_MAX_PORTS; i++) { - struct eud_path *path = chip->paths[i]; - - if (!path) - continue; - - if (path->eud_sw) - usb_role_switch_unregister(path->eud_sw); - if (path->controller_sw) - usb_role_switch_put(path->controller_sw); - } + usb_role_switch_put(chip->role_sw); } static int eud_init_path(struct eud_chip *chip, struct device_node *np) { - struct usb_role_switch_desc role_sw_desc = {}; struct eud_path *path; u32 path_num; int ret; @@ -381,32 +342,6 @@ static int eud_init_path(struct eud_chip *chip, struct device_node *np) chip->paths[path_num] = path; - path->curr_role = USB_ROLE_NONE; - - if (!of_property_read_bool(np, "usb-role-switch")) - return 0; - - /* Fetch the USB controller's role switch */ - path->controller_sw = fwnode_usb_role_switch_get(of_fwnode_handle(np)); - if (IS_ERR(path->controller_sw)) - return dev_err_probe(chip->dev, PTR_ERR(path->controller_sw), - "Failed to get controller role switch for path %d\n", - path_num); - - /* Create a role switch */ - role_sw_desc.fwnode = of_fwnode_handle(np); - role_sw_desc.set = eud_role_switch_set; - role_sw_desc.driver_data = path; - snprintf(path->name, sizeof(path->name), "eud-path%u", path_num); - role_sw_desc.name = path->name; - - path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc); - if (IS_ERR(path->eud_sw)) { - dev_err(chip->dev, "Failed to register EUD role switch for path %d: %ld\n", - path_num, PTR_ERR(path->eud_sw)); - return PTR_ERR(path->eud_sw); - } - return 0; } @@ -424,6 +359,11 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + chip->role_sw = usb_role_switch_get(&pdev->dev); + if (IS_ERR(chip->role_sw)) + return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), + "failed to get role switch\n"); + ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From 1483562653b069cb0b04eae1ad73a30c755d6eca Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:33 -0700 Subject: [PATCH 0948/1058] Revert "FROMLIST: usb: misc: qcom_eud: add per-path High-Speed PHY control" This reverts commit e2541a8409a99af58825af0a54178d0b26677f5b. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 130 +----------------------------------- 1 file changed, 1 insertion(+), 129 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 5cebb64f4a672..1a136f8f1ae52 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -35,95 +34,25 @@ #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) -struct eud_path { - struct eud_chip *chip; - struct phy *phy; - u8 num; -}; - struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; void __iomem *base; - struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; - bool phy_enabled; u8 port_idx; }; -static int eud_phy_enable(struct eud_chip *chip) -{ - struct eud_path *path; - struct phy *phy; - int ret; - - if (chip->phy_enabled) - return 0; - - path = chip->paths[chip->port_idx]; - if (!path || !path->phy) { - dev_err(chip->dev, "No PHY configured for port %u\n", chip->port_idx); - return -ENODEV; - } - - phy = path->phy; - - ret = phy_init(phy); - if (ret) { - dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", - chip->port_idx, ret); - return ret; - } - - ret = phy_power_on(phy); - if (ret) { - dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", - chip->port_idx, ret); - phy_exit(phy); - return ret; - } - - chip->phy_enabled = true; - - return 0; -} - -static void eud_phy_disable(struct eud_chip *chip) -{ - struct eud_path *path; - struct phy *phy; - - if (!chip->phy_enabled) - return; - - path = chip->paths[chip->port_idx]; - if (!path || !path->phy) - return; - - phy = path->phy; - - phy_power_off(phy); - phy_exit(phy); - chip->phy_enabled = false; -} - static int enable_eud(struct eud_chip *priv) { int ret; - ret = eud_phy_enable(priv); - if (ret) - return ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); - if (ret) { - eud_phy_disable(priv); + if (ret) return ret; - } writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, @@ -141,8 +70,6 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); - eud_phy_disable(priv); - return 0; } @@ -205,12 +132,6 @@ static ssize_t port_store(struct device *dev, if (port >= EUD_MAX_PORTS) return -EINVAL; - /* Check if the corresponding path is available */ - if (!chip->paths[port]) { - dev_err(chip->dev, "EUD not supported on selected port\n"); - return -EOPNOTSUPP; - } - /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -310,45 +231,8 @@ static void eud_role_switch_release(void *data) usb_role_switch_put(chip->role_sw); } -static int eud_init_path(struct eud_chip *chip, struct device_node *np) -{ - struct eud_path *path; - u32 path_num; - int ret; - - ret = of_property_read_u32(np, "reg", &path_num); - if (ret) { - dev_err(chip->dev, "Missing 'reg' property in path node\n"); - return ret; - } - - if (path_num >= EUD_MAX_PORTS) { - dev_err(chip->dev, "Invalid path number: %u (max %d)\n", - path_num, EUD_MAX_PORTS - 1); - return -EINVAL; - } - - path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL); - if (!path) - return -ENOMEM; - - path->chip = chip; - path->num = path_num; - - path->phy = devm_of_phy_get(chip->dev, np, NULL); - if (IS_ERR(path->phy)) - return dev_err_probe(chip->dev, PTR_ERR(path->phy), - "Failed to get PHY for path %d\n", path_num); - - chip->paths[path_num] = path; - - return 0; -} - static int eud_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct device_node *child; struct eud_chip *chip; struct resource *res; int ret; @@ -368,18 +252,6 @@ static int eud_probe(struct platform_device *pdev) if (ret) return ret; - for_each_child_of_node(np, child) { - ret = eud_init_path(chip, child); - if (ret) { - of_node_put(child); - return ret; - } - } - - /* Primary path is mandatory. Secondary is optional */ - if (!chip->paths[0]) - return -ENODEV; - chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) return PTR_ERR(chip->base); From c9707f04c077eb69816b211cfbfa343dcb211a1b Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:52 -0700 Subject: [PATCH 0949/1058] Revert "FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection" This reverts commit c042ed7b42aff071249d6a1b91cedb7170e2d2d4. Signed-off-by: Elson Serrao --- Documentation/ABI/testing/sysfs-driver-eud | 16 -------- drivers/usb/misc/qcom_eud.c | 43 ---------------------- 2 files changed, 59 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 67223f73ee606..2bab0db2d2f0f 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,19 +7,3 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. - -What: /sys/bus/platform/drivers/qcom_eud/.../port -Date: January 2026 -Contact: Elson Serrao -Description: - Selects which USB port the Embedded USB Debugger (EUD) - is mapped to on platforms providing multiple High-Speed - USB ports. - - Valid values: - 0 - Primary USB port - 1 - Secondary USB port - - The attribute is writable only while EUD is disabled. - Reading the attribute returns the currently selected - USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 1a136f8f1ae52..926419ca560fc 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,11 +23,8 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 -#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 -#define EUD_MAX_PORTS 2 - #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -43,7 +40,6 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; - u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -108,47 +104,8 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); -static ssize_t port_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct eud_chip *chip = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%u\n", chip->port_idx); -} - -static ssize_t port_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct eud_chip *chip = dev_get_drvdata(dev); - u8 port; - int ret; - - ret = kstrtou8(buf, 0, &port); - if (ret) - return ret; - - /* Only port 0 and port 1 are valid */ - if (port >= EUD_MAX_PORTS) - return -EINVAL; - - /* Port selection must be done before enabling EUD */ - if (chip->enabled) { - dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); - return -EBUSY; - } - - writel(port, chip->base + EUD_REG_PORT_SEL); - chip->port_idx = port; - - return count; -} - -static DEVICE_ATTR_RW(port); - static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, - &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 51324352f7a58b743142989e5162581ec7d08500 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:22:10 -0700 Subject: [PATCH 0950/1058] Revert "FROMLIST: dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware" This reverts commit cfe135bf3401dee9bbb5c726594894cc453d28ea. Signed-off-by: Elson Serrao --- .../bindings/soc/qcom/qcom,eud.yaml | 100 +++++------------- 1 file changed, 26 insertions(+), 74 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 0507252dbf27e..84218636c0d8d 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -10,11 +10,8 @@ maintainers: - Souradeep Chowdhury description: - This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip - mini USB hub that enables USB-based debug capabilities. The EUD block is - positioned between the High-Speed USB PHY and the USB controller, where it - intercepts the UTMI interface to support debug and bypass modes. EUD can be - supported on up to two High-Speed USB ports. + This binding is used to describe the Qualcomm Embedded USB Debugger, which is + mini USB-hub implemented on chip to support USB-based debug capabilities. properties: compatible: @@ -32,62 +29,26 @@ properties: description: EUD interrupt maxItems: 1 - '#address-cells': - const: 1 - - '#size-cells': - const: 0 - -patternProperties: - "^eud-path@[0-1]$": - type: object + ports: + $ref: /schemas/graph.yaml#/properties/ports description: - Represents one High-Speed UTMI path that EUD intercepts. This node models - the physical data path intercepted by EUD and provides graph endpoints to - link the USB controller and the external connector associated with this path. + These ports is to be attached to the endpoint of the DWC3 controller node + and type C connector node. The controller has the "usb-role-switch" + property. properties: - reg: - maxItems: 1 - description: Path number - - phys: - maxItems: 1 - description: High-Speed USB PHY associated with this data path. - - usb-role-switch: - type: boolean - description: - Set this property if the USB port on this path is role switch capable. - In device role, debug mode inserts the EUD hub into the UTMI path. In - host role, the EUD hub is bypassed and UTMI traffic flows directly - between the PHY and the USB controller. - - ports: - $ref: /schemas/graph.yaml#/properties/ports - description: - These ports are to be attached to the endpoint of the USB controller node - and USB connector node. - - properties: - port@0: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the USB controller. + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the DWC3 controller. - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the USB connector. - - required: - - reg - - phys - - ports - - additionalProperties: false + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the type C connector. required: - compatible - reg + - ports additionalProperties: false @@ -97,30 +58,21 @@ examples: compatible = "qcom,sc7280-eud", "qcom,eud"; reg = <0x88e0000 0x2000>, <0x88e2000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - - eud-path@0 { - reg = <0>; - phys = <&usb_1_hsphy>; - usb-role-switch; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; }; + }; - port@1 { - reg = <1>; - eud_con: endpoint { - remote-endpoint = <&con_eud>; - }; + port@1 { + reg = <1>; + eud_con: endpoint { + remote-endpoint = <&con_eud>; }; }; }; From c0baeced125e6a1936c46520969bb170ab74383b Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:22:28 -0700 Subject: [PATCH 0951/1058] =?UTF-8?q?FROMLIST:=20dt-bindings:=20connector:?= =?UTF-8?q?=20Add=20role=E2=80=91switch=20provider=20phandle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional consumer→provider phandle on USB connectors to reference the USB role-switch provider when no direct graph link exists. The DRD controller remains the provider via its 'usb-role-switch' property. Link: https://lore.kernel.org/all/20260223191042.825136-2-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- .../devicetree/bindings/connector/usb-connector.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml index 8ca0292490a2c..ecad7781644ce 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml @@ -95,6 +95,14 @@ properties: - device - dual + usb-role-switch: + $ref: /schemas/types.yaml#/definitions/phandle + description: + A phandle to the USB role-switch provider. The provider is typically + a dual-role (DRD) USB controller node that declares the boolean + 'usb-role-switch' property. Use this when the connector is not + directly linked to the provider in the OF graph. + typec-power-opmode: description: Determines the power operation mode that the Type C connector will support and will advertise through CC pins when it has no power From 4adc411813aeca96f1b9b94d7c567b8fc64a1165 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:23:13 -0700 Subject: [PATCH 0952/1058] FROMLIST: dt-bindings: soc: qcom: eud: Add support for dual-port configuration EUD hardware supports debugging on up to two USB ports depending on the SoC configuration. Debugging can be selected on either the primary or secondary USB port as controlled by the EUD_PORT_SELECT register. Extend the binding to support dual-port configurations by adding port@2 and port@3 for secondary USB controller and Type-C connector connections. Link: https://lore.kernel.org/all/20260309203337.803986-2-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- .../bindings/soc/qcom/qcom,eud.yaml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 84218636c0d8d..12560342f37fb 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -32,18 +32,27 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports description: - These ports is to be attached to the endpoint of the DWC3 controller node - and type C connector node. The controller has the "usb-role-switch" - property. + These ports attach to endpoints of DWC3 controller nodes and Type-C + connector nodes. The controller has the "usb-role-switch" property. + EUD supports up to 2 USB ports. For single-port configurations, use + port@0 and port@1. For dual-port configurations, use all four ports. properties: port@0: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the DWC3 controller. + description: This port is to be attached to the primary DWC3 controller. port@1: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the type C connector. + description: This port is to be attached to the primary Type-C connector. + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary DWC3 controller. + + port@3: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary Type-C connector. required: - compatible From c2052b2d61bc0f14f4a0431ef477708379891092 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:23:36 -0700 Subject: [PATCH 0953/1058] FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection EUD can be mapped to either the primary USB port or the secondary USB port depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs attribute to allow userspace to select which port EUD should operate on and update the ABI documentation. This is needed for systems with dual USB ports where EUD needs to be accessible on either port depending on the system configuration and use case. Link: https://lore.kernel.org/all/20260309203337.803986-3-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- Documentation/ABI/testing/sysfs-driver-eud | 16 +++++++++ drivers/usb/misc/qcom_eud.c | 41 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 2bab0db2d2f0f..67223f73ee606 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,3 +7,19 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. + +What: /sys/bus/platform/drivers/qcom_eud/.../port +Date: January 2026 +Contact: Elson Serrao +Description: + Selects which USB port the Embedded USB Debugger (EUD) + is mapped to on platforms providing multiple High-Speed + USB ports. + + Valid values: + 0 - Primary USB port + 1 - Secondary USB port + + The attribute is writable only while EUD is disabled. + Reading the attribute returns the currently selected + USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 926419ca560fc..35324e1e1ea7e 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,8 +23,11 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 +#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 +#define EUD_MAX_PORTS 2 + #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -40,6 +43,7 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; + u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -104,8 +108,45 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); +static ssize_t port_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", chip->port_idx); +} + +static ssize_t port_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + u8 port; + int ret; + + ret = kstrtou8(buf, 0, &port); + if (ret) + return ret; + + /* Only port 0 and port 1 are valid */ + if (port >= EUD_MAX_PORTS) + return -EINVAL; + + /* Port selection must be done before enabling EUD */ + if (chip->enabled) { + dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); + return -EBUSY; + } + + writel(port, chip->base + EUD_REG_PORT_SEL); + chip->port_idx = port; + + return count; +} + +static DEVICE_ATTR_RW(port); + static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, + &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 64ef5e3e829b19418767771831982f94f54a807f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:35 -0700 Subject: [PATCH 0954/1058] FROMLIST: usb: misc: qcom_eud: add per-port High-Speed PHY control EUD hardware can support multiple High-Speed USB ports, each routed through its own PHY. The active port is selected in hardware via the EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the High-Speed PHY associated with the active port. To support this multi-port capability, the driver must manage PHY resources on a per-port basis, ensuring that the PHY for the currently selected port is properly initialized and powered. This patch adds per-port PHY management to the driver. The driver now powers the appropriate PHY based on the selected and enabled port, ensuring correct operation when EUD is enabled. Historically, EUD appeared to work on single-port systems because the USB controller kept the PHY initialized. However, EUD is designed to operate independently of the USB controller and therefore requires explicit PHY control for proper operation. Link: https://lore.kernel.org/all/20260309203337.803986-4-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/Kconfig | 1 + drivers/usb/misc/qcom_eud.c | 103 +++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 91b62acb537b3..4c0aa718ef267 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -147,6 +147,7 @@ config USB_APPLEDISPLAY config USB_QCOM_EUD tristate "Qualcomm Embedded USB Debugger(EUD) Driver" depends on ARCH_QCOM || COMPILE_TEST + depends on OF select QCOM_SCM select USB_ROLE_SWITCH help diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 35324e1e1ea7e..571b21323797b 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,23 +39,75 @@ struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; + struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; + bool phy_enabled; u8 port_idx; }; +static int eud_phy_enable(struct eud_chip *chip) +{ + struct phy *phy; + int ret; + + if (chip->phy_enabled) + return 0; + + phy = chip->phy[chip->port_idx]; + + ret = phy_init(phy); + if (ret) { + dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + return ret; + } + + ret = phy_power_on(phy); + if (ret) { + dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + phy_exit(phy); + return ret; + } + + chip->phy_enabled = true; + + return 0; +} + +static void eud_phy_disable(struct eud_chip *chip) +{ + struct phy *phy; + + if (!chip->phy_enabled) + return; + + phy = chip->phy[chip->port_idx]; + + phy_power_off(phy); + phy_exit(phy); + chip->phy_enabled = false; +} + static int enable_eud(struct eud_chip *priv) { int ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + ret = eud_phy_enable(priv); if (ret) return ret; + ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + if (ret) { + eud_phy_disable(priv); + return ret; + } + writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); @@ -70,6 +124,8 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); + eud_phy_disable(priv); + return 0; } @@ -130,6 +186,11 @@ static ssize_t port_store(struct device *dev, struct device_attribute *attr, if (port >= EUD_MAX_PORTS) return -EINVAL; + if (!chip->phy[port]) { + dev_err(chip->dev, "EUD not supported on selected port\n"); + return -EOPNOTSUPP; + } + /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -222,6 +283,35 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } +static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) +{ + struct device_node *controller_node; + struct phy *phy; + + /* + * Multiply port_id by 2 to get controller port number: + * port_id 0 -> port@0 (primary USB controller) + * port_id 1 -> port@2 (secondary USB controller) + */ + controller_node = of_graph_get_remote_node(chip->dev->of_node, + port_id * 2, -1); + if (!controller_node) + return dev_err_probe(chip->dev, -ENODEV, + "failed to get controller node for port %u\n", port_id); + + phy = devm_of_phy_get_by_index(chip->dev, controller_node, 0); + if (IS_ERR(phy)) { + of_node_put(controller_node); + return dev_err_probe(chip->dev, PTR_ERR(phy), + "failed to get HS PHY for port %u\n", port_id); + } + chip->phy[port_id] = phy; + + of_node_put(controller_node); + + return 0; +} + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; @@ -241,6 +331,17 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + /* + * Parse the DT resources for primary port. + * This is the default EUD port and is mandatory. + */ + ret = eud_parse_dt_port(chip, 0); + if (ret) + return ret; + + /* Secondary port is optional */ + eud_parse_dt_port(chip, 1); + chip->role_sw = usb_role_switch_get(&pdev->dev); if (IS_ERR(chip->role_sw)) return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), From f2c0e913e68c9365f2b588d0af5f98e5a9fb4ec3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0955/1058] FROMLIST: usb: misc: qcom_eud: add per-port role switch support The EUD hardware can support multiple High-Speed USB ports, each connected to different USB controllers. The current implementation uses a single chip-level role switch, which cannot properly handle multi-port configurations where each USB port can operate in different role. Restructure the driver to support per-port role switches. Additionally, remove the unnecessary role switch call from enable_eud() as EUD need not modify the USB role upon enabling. Link: https://lore.kernel.org/all/20260309203337.803986-5-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 571b21323797b..c484fc88dea4d 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,7 +38,7 @@ struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw; + struct usb_role_switch *role_sw[EUD_MAX_PORTS]; struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; @@ -112,7 +112,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); + return 0; } static int disable_eud(struct eud_chip *priv) @@ -270,9 +270,9 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) int ret; if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); @@ -287,6 +287,7 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) { struct device_node *controller_node; struct phy *phy; + struct usb_role_switch *role_sw; /* * Multiply port_id by 2 to get controller port number: @@ -307,16 +308,31 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) } chip->phy[port_id] = phy; + /* Only fetch role switch if usb-role-switch property exists */ + if (!of_property_read_bool(controller_node, "usb-role-switch")) { + of_node_put(controller_node); + return 0; + } + + role_sw = usb_role_switch_find_by_fwnode(of_fwnode_handle(controller_node)); of_node_put(controller_node); + if (!role_sw) + return dev_err_probe(chip->dev, -EPROBE_DEFER, + "failed to get role switch for port %u\n", port_id); + + chip->role_sw[port_id] = role_sw; + return 0; } static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; + int i; - usb_role_switch_put(chip->role_sw); + for (i = 0; i < EUD_MAX_PORTS; i++) + usb_role_switch_put(chip->role_sw[i]); } static int eud_probe(struct platform_device *pdev) @@ -342,11 +358,6 @@ static int eud_probe(struct platform_device *pdev) /* Secondary port is optional */ eud_parse_dt_port(chip, 1); - chip->role_sw = usb_role_switch_get(&pdev->dev); - if (IS_ERR(chip->role_sw)) - return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), - "failed to get role switch\n"); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From 1abc533bf16b038fd9f3f7998b4bcfc0a933fdd0 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0956/1058] FROMLIST: usb: misc: qcom_eud: improve enable_store API Currently enable_store() allows operations irrespective of the EUD state, which can result in redundant operations. Avoid this by adding duplicate state checks to skip requests when EUD is already in the desired state. Additionally, improve error handling with explicit logging to provide better feedback. Link: https://lore.kernel.org/all/20260309203337.803986-6-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- drivers/usb/misc/qcom_eud.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index c484fc88dea4d..eee79774f5f8d 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -148,18 +148,27 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; + /* Skip operation if already in desired state */ + if (chip->enabled == enable) + return count; + if (enable) { ret = enable_eud(chip); - if (!ret) - chip->enabled = enable; - else - disable_eud(chip); - + if (ret) { + dev_err(chip->dev, "failed to enable eud\n"); + return ret; + } } else { ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable eud\n"); + return ret; + } } - return ret < 0 ? ret : count; + chip->enabled = enable; + + return count; } static DEVICE_ATTR_RW(enable); From 0383a15688997f81a2938007ae9e52c3a17276e8 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0957/1058] FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling EUD provides virtual USB attach/detach events to simulate cable plug/unplug while maintaining the physical debug connection. However, the current implementation incorrectly sets the USB role to HOST on virtual detach, which doesn't represent the disconnected state. Fix the virtual detach handling by setting the USB role to NONE instead of HOST, correctly representing the disconnected state. Link: https://lore.kernel.org/all/20260309203337.803986-7-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- drivers/usb/misc/qcom_eud.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index eee79774f5f8d..ae0c5b2f022a2 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -278,10 +278,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) struct eud_chip *chip = data; int ret; + /* + * EUD virtual attach/detach event handling for low power debugging: + * + * When EUD is enabled in debug mode, the device remains physically + * connected to the PC throughout the debug session, keeping the USB + * controller active. This prevents testing of low power scenarios that + * require USB disconnection. + * + * EUD solves this by providing virtual USB attach/detach events while + * maintaining the physical connection. These events are triggered from + * the Host PC via the enumerated EUD control interface and delivered + * to the EUD driver as interrupts. + * + * These notifications are forwarded to the USB controller through role + * switch framework. + */ if (chip->usb_attached) ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From aa09ae014d56b97efa9a6bfb59e8e7db692165b8 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:37 -0700 Subject: [PATCH 0958/1058] FROMLIST: usb: misc: qcom_eud: add host mode coordination EUD functions by presenting itself as a USB device to the host PC for debugging, making it incompatible with USB host mode configurations. Handle below two scenarios to prevent these conflicts: 1. Prevent user from enabling EUD via sysfs when the USB port is in host mode. 2. Automatically disable EUD when USB port switches to host mode and re-enable it when exiting host mode. This is achieved via the exported qcom_eud_usb_role_notify() API that allows the USB controller driver to notify EUD of role changes. This ensures consistent state management without creating conflicts between the EUD debug hub and the USB controller. Link: https://lore.kernel.org/all/20260309203337.803986-8-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 110 ++++++++++++++++++++++++++++++++++- include/linux/usb/qcom_eud.h | 21 +++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 include/linux/usb/qcom_eud.h diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index ae0c5b2f022a2..5b5cf11d6f526 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -12,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #define EUD_REG_INT1_EN_MASK 0x0024 @@ -42,11 +44,14 @@ struct eud_chip { struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; + /* serializes EUD control operations */ + struct mutex state_lock; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; + bool eud_disabled_for_host; u8 port_idx; }; @@ -142,17 +147,43 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); + enum usb_role role; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; + guard(mutex)(&chip->state_lock); + /* Skip operation if already in desired state */ if (chip->enabled == enable) return count; + /* + * Handle double-disable scenario: User is disabling EUD that was already + * disabled due to host mode. Since the hardware is already disabled, we + * only need to clear the host-disabled flag to prevent unwanted re-enabling + * when exiting host mode. This respects the user's explicit disable request. + */ + if (!enable && chip->eud_disabled_for_host) { + chip->eud_disabled_for_host = false; + chip->enabled = false; + return count; + } + if (enable) { + /* + * EUD functions by presenting itself as a USB device to the host PC for + * debugging, making it incompatible with USB host mode configuration. + * Prevent enabling EUD in this configuration to avoid hardware conflicts. + */ + role = usb_role_switch_get_role(chip->role_sw[chip->port_idx]); + if (role == USB_ROLE_HOST) { + dev_err(chip->dev, "Cannot enable EUD: USB port is in host mode\n"); + return -EBUSY; + } + ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); @@ -351,6 +382,75 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) return 0; } +/** + * qcom_eud_usb_role_notify - Notify EUD of USB role change + * @eud_node: Device node of the EUD device + * @phy: HSUSB PHY of the port changing role + * @role: New role being set + * + * Notifies EUD that a USB port is changing roles. EUD will disable itself + * if the port is switching to HOST mode, as EUD is incompatible with host + * mode operation. This API should be called by the USB controller driver + * when it switches the USB role. + * + * The PHY parameter is used to identify which physical USB port is changing + * roles. This is important in multi-port systems where EUD may be active on + * one port while another port changes roles. + * + * This is a best-effort notification - failures are logged but do not affect + * the role change operation. + */ +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ + struct platform_device *pdev; + struct eud_chip *chip; + int ret; + + if (!of_device_is_compatible(eud_node, "qcom,eud")) + return; + + pdev = of_find_device_by_node(eud_node); + if (!pdev) + return; + + chip = platform_get_drvdata(pdev); + if (!chip) + goto put_dev; + + mutex_lock(&chip->state_lock); + + /* Only act if this notification is for the currently active EUD port */ + if (!chip->enabled || chip->phy[chip->port_idx] != phy) { + mutex_unlock(&chip->state_lock); + goto put_dev; + } + + /* + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to preserve user intent. + */ + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", ret); + else + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", ret); + else + chip->eud_disabled_for_host = false; + } + + mutex_unlock(&chip->state_lock); + +put_dev: + platform_device_put(pdev); +} +EXPORT_SYMBOL_GPL(qcom_eud_usb_role_notify); + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; @@ -372,6 +472,8 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + mutex_init(&chip->state_lock); + /* * Parse the DT resources for primary port. * This is the default EUD port and is mandatory. @@ -416,8 +518,14 @@ static void eud_remove(struct platform_device *pdev) { struct eud_chip *chip = platform_get_drvdata(pdev); - if (chip->enabled) + platform_set_drvdata(pdev, NULL); + + mutex_lock(&chip->state_lock); + if (chip->enabled) { disable_eud(chip); + chip->enabled = false; + } + mutex_unlock(&chip->state_lock); device_init_wakeup(&pdev->dev, false); disable_irq_wake(chip->irq); diff --git a/include/linux/usb/qcom_eud.h b/include/linux/usb/qcom_eud.h new file mode 100644 index 0000000000000..fe560426b78f3 --- /dev/null +++ b/include/linux/usb/qcom_eud.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __LINUX_USB_QCOM_EUD_H +#define __LINUX_USB_QCOM_EUD_H + +#include + +#if IS_ENABLED(CONFIG_USB_QCOM_EUD) +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role); +#else +static inline void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ +} +#endif + +#endif /* __LINUX_USB_QCOM_EUD_H */ From 500d053aab949b7b2a73e69334e0000aaca4eb01 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:37 -0700 Subject: [PATCH 0959/1058] FROMLIST: usb: dwc3: qcom: notify EUD driver of role changes The EUD driver needs USB role information to control its operation as it is incompatible with host mode. Notify the EUD driver when role changes occur so it can manage its state accordingly. Link: https://lore.kernel.org/all/20260309203337.803986-9-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/dwc3/Kconfig | 1 + drivers/usb/dwc3/dwc3-qcom.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 18169727a413e..ae03ae45e50e4 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -132,6 +132,7 @@ config USB_DWC3_QCOM depends on ARCH_QCOM || COMPILE_TEST depends on EXTCON || !EXTCON depends on OF + depends on USB_QCOM_EUD || !USB_QCOM_EUD default USB_DWC3 help Some Qualcomm SoCs use DesignWare Core IP for USB2/3 diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f43f73ac36ff1..4c00b6b87f6d5 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include "core.h" #include "glue.h" @@ -561,6 +563,7 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role) { struct dwc3_qcom *qcom = to_dwc3_qcom(dwc); + struct device_node *eud_node; if (qcom->current_role == next_role) return; @@ -570,6 +573,13 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol return; } + /* Notify EUD of role change */ + eud_node = of_graph_get_remote_node(qcom->dev->of_node, 0, -1); + if (eud_node) { + qcom_eud_usb_role_notify(eud_node, dwc->usb2_generic_phy[0], next_role); + of_node_put(eud_node); + } + if (qcom->current_role == USB_ROLE_DEVICE) dwc3_qcom_vbus_override_enable(qcom, false); else if (qcom->current_role != USB_ROLE_DEVICE) From 00c6452c414650e320d6ac20db559381134195cd Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:38 -0700 Subject: [PATCH 0960/1058] FROMLIST: arm64: dts: qcom: kodiak: Fix EUD USB controller connection The EUD node is currently mapped to the secondary USB controller. This SoC only supports EUD on the primary High-Speed USB path. Fix the graph connections to properly map EUD to the primary USB controller. Add an empty connector endpoint for board DTS files to complete the connection. Also enable EUD so debug is available by default on this SoC. Link: https://lore.kernel.org/all/20260309203337.803986-10-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..ffb11896ccfa1 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,12 +4404,6 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; - - port { - usb2_role_switch: endpoint { - remote-endpoint = <&eud_ep>; - }; - }; }; qspi: spi@88dc000 { @@ -4736,16 +4730,22 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; - ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; + eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + eud_con: endpoint { }; }; }; @@ -4972,6 +4972,7 @@ reg = <0>; usb_1_dwc3_hs: endpoint { + remote-endpoint = <&eud_ep>; }; }; From c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:38 -0700 Subject: [PATCH 0961/1058] FROMLIST: arm64: dts: qcom: Map USB connector to EUD for kodiak boards Map the USB connector HS endpoint to EUD for debug functionality on all boards using kodiak.dtsi. Since the controller is no longer a direct neighbor of the connector, add usb-role-switch phandle to map the USB role switch provider for this connector. Link: https://lore.kernel.org/all/20260309203337.803986-11-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 11 ++++++----- .../boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts | 11 ++++++----- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts index 04cb9230d29fd..9f0cfd0b5005e 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts @@ -89,6 +89,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -98,7 +99,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1478,10 +1479,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -1521,3 +1518,7 @@ qcom,calibration-variant = "Fairphone_5"; status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts index bf18c48520813..ca9c1a09ca733 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts @@ -65,6 +65,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -74,7 +75,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -826,10 +827,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -862,3 +859,7 @@ &usb_dp_qmpphy_out { remote-endpoint = <&pmic_glink_ss_in>; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts index 797f37596bf19..eb7e228787c24 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts @@ -75,6 +75,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -84,7 +85,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -952,10 +953,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -986,6 +983,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &venus { firmware-name = "qcom/qcm6490/SHIFT/otter/venus.mbn"; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..4de0576c0f2fe 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -202,6 +202,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -211,7 +212,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1402,14 +1403,14 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index f47efca42d48d..05cd73b5bcbe2 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -84,6 +84,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -93,7 +94,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1090,10 +1091,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -1127,6 +1124,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>; vcc-supply = <&vreg_l7b_2p952>; diff --git a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts index cb59c122f6f6a..f99a47334452f 100644 --- a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts +++ b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts @@ -90,6 +90,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -99,7 +100,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1440,10 +1441,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vdd_a_usbhs_core>; vdda18-supply = <&vdd_a_usbhs_1p8>; @@ -1459,3 +1456,7 @@ &wifi { status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; From 88eac183e3f4545f404c6f56921f0b6377d8c005 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 21 Oct 2025 10:39:54 +0530 Subject: [PATCH 0962/1058] UPSTREAM: dt-bindings: usb: qcom,snps-dwc3: Add the SM8750 compatible Add qcom,sm8750-dwc3 compatible to flattened implementation binding. Link: https://lore.kernel.org/all/20251021050954.3462613-1-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Signed-off-by: Krishna Kurapati Reviewed-by: Krzysztof Kozlowski From 7e182661ea820aeaf38dfdd1362131b3b7d97948 Mon Sep 17 00:00:00 2001 From: Melody Olvera Date: Wed, 15 Oct 2025 16:22:07 +0530 Subject: [PATCH 0963/1058] FROMLIST: dt-bindings: usb: qcom,dwc3: Correct the SM8750 compatible SM8750 does not require an XO clock in the dt as it is the parent of the TCSR refclk_src, so move the compatible to a section where the XO clock is not required. Acked-by: Krzysztof Kozlowski Signed-off-by: Melody Olvera Signed-off-by: Krishna Kurapati Link: https://lore.kernel.org/all/20251015105207.2819689-1-krishna.kurapati@oss.qualcomm.com/#r Signed-off-by: Yash Gupta --- Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index a7f58114c02e8..2e2d4562fb03c 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -227,6 +227,7 @@ allOf: - qcom,sdx65-dwc3 - qcom,sdx75-dwc3 - qcom,sm6350-dwc3 + - qcom,sm8750-dwc3 then: properties: clocks: @@ -366,7 +367,6 @@ allOf: - qcom,sm8450-dwc3 - qcom,sm8550-dwc3 - qcom,sm8650-dwc3 - - qcom,sm8750-dwc3 then: properties: clocks: From 9dd47ad7e5c1dea9cfbcdd3f5e84af8d647af95f Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Mon, 11 May 2026 15:14:22 +0530 Subject: [PATCH 0964/1058] FROMLIST: usb: dwc3: qcom: Modify interrupt handling for eUSB2 Phy targets eUSB2 targets handle wakeup interrupts differently depending on device speed when operating in host mode. According to the eUSB2 specification, remote wakeup signaling in host mode is detected via different data-line assertions based on the connected device speed. When a low-speed device is connected, the host repeater drives eD+ to logic '1' upon detecting a K-state on the USB lines during remote wakeup (eUSB2 specification, Section 5.5.14). When a full-speed or high-speed device is connected, the host repeater drives eD- to logic '1' upon detecting a K-state on the USB line during remote wakeup (eUSB2 specification, Sections 5.5.15 and 5.5.18). Since the eUSB2 PHY's "DP" and "DM" interrupt lines monitor the eD+ and eD- line states, configure the wakeup interrupts accordingly Link: https://lore.kernel.org/all/20260511094422.3561509-1-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati Signed-off-by: Pratham Pratap --- drivers/usb/dwc3/dwc3-qcom.c | 94 +++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f43f73ac36ff1..3b025d4beeaeb 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -60,6 +60,10 @@ static const u32 pwr_evnt_irq_stat_reg[DWC3_QCOM_MAX_PORTS] = { 0x238, }; +struct dwc3_qcom_platform_data { + bool uses_eusb2_phy; +}; + struct dwc3_qcom_port { int qusb2_phy_irq; int dp_hs_phy_irq; @@ -85,6 +89,7 @@ struct dwc3_qcom { struct icc_path *icc_path_apps; enum usb_role current_role; + bool uses_eusb2_phy; }; #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc) @@ -272,15 +277,23 @@ static void dwc3_qcom_disable_wakeup_irq(int irq) disable_irq_nosync(irq); } -static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq); if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); } else { dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); @@ -289,8 +302,10 @@ static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq); } -static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0); /* @@ -303,12 +318,20 @@ static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) */ if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else { dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, IRQ_TYPE_EDGE_RISING); @@ -324,7 +347,7 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_disable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_disable_port_interrupts(qcom, i); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -332,7 +355,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_enable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_enable_port_interrupts(qcom, i); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -609,6 +632,7 @@ struct dwc3_glue_ops dwc3_qcom_glue_ops = { static int dwc3_qcom_probe(struct platform_device *pdev) { + const struct dwc3_qcom_platform_data *pdata; struct dwc3_probe_data probe_data = {}; struct device *dev = &pdev->dev; struct dwc3_qcom *qcom; @@ -624,6 +648,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) qcom->dev = &pdev->dev; + pdata = device_get_match_data(dev); + if (pdata) + qcom->uses_eusb2_phy = pdata->uses_eusb2_phy; + qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(qcom->resets)) { return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), @@ -838,8 +866,52 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { .prepare = pm_sleep_ptr(dwc3_qcom_prepare), }; +static const struct dwc3_qcom_platform_data dwc3_qcom_glymur_pdata = { + .uses_eusb2_phy = true, +}; + static const struct of_device_id dwc3_qcom_of_match[] = { - { .compatible = "qcom,snps-dwc3" }, + { .compatible = "qcom,snps-dwc3", }, + { + .compatible = "qcom,eliza-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,kaanapali-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,milos-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8550-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8650-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8750-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, { } }; MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match); From a91544020bd06f83313c1544f2f94d7c19064843 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Fri, 19 Jun 2026 21:47:50 +0800 Subject: [PATCH 0965/1058] FROMLIST: wifi: ath12k: fix rx_mpdu_start layout for QCC2072 QCC2072's rx_mpdu_start TLV has a different field layout from QCN9274. Reusing struct rx_mpdu_start_qcn9274 in hal_rx_desc_qcc2072 causes the RX datapath to read the wrong offsets for info2, info4, pn[] and phy_ppdu_id, producing corrupted sequence number, PN, ppdu_id and mpdu-info flags (encrypted, fragment, addr2/addr4 valid). Add a dedicated struct rx_mpdu_start_qcc2072 that matches the actual hardware descriptor layout, and use it in hal_rx_desc_qcc2072. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00188-QCACOLSWPL_V1_TO_SILICONZ-1 Fixes: 28badc78142e ("wifi: ath12k: add HAL descriptor and ops for QCC2072") Link: https://lore.kernel.org/linux-wireless/20260629061529.1993932-1-wei.zhang@oss.qualcomm.com/ Signed-off-by: Wei Zhang --- .../wireless/ath/ath12k/wifi7/hal_rx_desc.h | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h index 0d19a9cbb68ce..6d69851e529d8 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h @@ -140,6 +140,38 @@ struct rx_mpdu_start_qcn9274 { __le32 res1; } __packed; +struct rx_mpdu_start_qcc2072 { + __le32 info0; + __le32 info2; + __le32 reo_queue_desc_lo; + __le32 info1; + __le32 pn[4]; + __le32 info4; + __le32 peer_meta_data; + __le16 ast_index; + __le16 sw_peer_id; + __le16 info3; + __le16 phy_ppdu_id; + __le32 info5; + __le32 info6; + __le16 frame_ctrl; + __le16 duration; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctrl; + u8 addr4[ETH_ALEN]; + __le16 qos_ctrl; + __le32 ht_ctrl; + __le32 info7; + __le32 res0; + __le32 res1; + __le32 res2; + __le32 info8; + __le32 res3; + __le32 res4; +} __packed; + #define QCN9274_MPDU_START_SELECT_MPDU_START_TAG BIT(0) #define QCN9274_MPDU_START_SELECT_INFO0_REO_QUEUE_DESC_LO BIT(1) #define QCN9274_MPDU_START_SELECT_INFO1_PN_31_0 BIT(2) @@ -1492,7 +1524,7 @@ struct hal_rx_desc_qcc2072 { struct rx_msdu_end_qcn9274 msdu_end; u8 rx_padding0[RX_BE_PADDING0_BYTES]; __le32 mpdu_start_tag; - struct rx_mpdu_start_qcn9274 mpdu_start; + struct rx_mpdu_start_qcc2072 mpdu_start; struct rx_pkt_hdr_tlv_qcc2072 pkt_hdr_tlv; u8 msdu_payload[]; }; From cb96f0691662ec18e92c2cbc483351e4ebdf11f5 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 3 Jul 2026 10:07:42 +0800 Subject: [PATCH 0966/1058] PENDING: arm64: dts: qcom: sm8750: add Coresight devices for APSS debug block Add the following devices that are part of the APSS debug block to enable debug features, including ETM, replicator, funnel, and TMC ETF. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/sm8750-staging.dtso | 636 +++++++++++++++++++ 1 file changed, 636 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750-staging.dtso b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso index 68c477c63a328..c9741b3832dd4 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-staging.dtso +++ b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso @@ -8,7 +8,160 @@ /dts-v1/; /plugin/; +&{/} { + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; +}; + &soc { + tn@109ab000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@21 { + reg = <0x21>; + + tn_ag_in33: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; + tgu@10b0e000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x10b0e000 0x0 0x1000>; @@ -32,4 +185,487 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in33>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@13481000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13481000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@134d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@134e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@13d01000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13d01000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13d09000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13d09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@13d81000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13d81000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13d90000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13d90000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@13da0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13da0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; }; From e19df3542351dab2e80fed965166b51e157afdff Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Wed, 20 May 2026 15:44:29 +0530 Subject: [PATCH 0967/1058] soc: qcom: smsm: Add trace events Add ftrace tracepoints to SMSM for observability of state bit updates, IPC kicks, interrupt handling, and IRQ mask/unmask operations. Introduce a trace header and wire CFLAGS_smsm.o so the trace header is found via -I$(src). Signed-off-by: Vishnu Santhosh --- drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/smsm.c | 18 ++++- drivers/soc/qcom/trace-smsm.h | 143 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/qcom/trace-smsm.h diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index b7f1d2a573674..dfa81237936d2 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_QCOM_SMEM) += smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o CFLAGS_smp2p.o := -I$(src) obj-$(CONFIG_QCOM_SMP2P) += smp2p.o +CFLAGS_smsm.o := -I$(src) obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o obj-$(CONFIG_QCOM_SPM) += spm.o diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 7d1823ab4198b..5d62076024567 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -15,6 +15,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace-smsm.h" + /* * This driver implements the Qualcomm Shared Memory State Machine, a mechanism * for communicating single bit state information to remote processors. @@ -162,6 +165,9 @@ static int smsm_update_bits(void *data, u32 mask, u32 value) /* Don't signal if we didn't change the value */ changes = val ^ orig; + + trace_smsm_update_bits(smsm->dev, mask, value, orig, val, changes); + if (!changes) { spin_unlock_irqrestore(&smsm->lock, flags); goto done; @@ -182,6 +188,8 @@ static int smsm_update_bits(void *data, u32 mask, u32 value) if (!(val & changes)) continue; + trace_smsm_ipc_kick(smsm->dev, host, val); + if (hostp->mbox_chan) { mbox_send_message(hostp->mbox_chan, NULL); mbox_client_txdone(hostp->mbox_chan, 0); @@ -214,10 +222,14 @@ static irqreturn_t smsm_intr(int irq, void *data) unsigned i; int irq_pin; u32 changed; + u32 old; u32 val; val = readl(entry->remote_state); - changed = val ^ xchg(&entry->last_value, val); + old = xchg(&entry->last_value, val); + changed = val ^ old; + + trace_smsm_intr(irq, old, val, changed); for_each_set_bit(i, entry->irq_enabled, 32) { if (!(changed & BIT(i))) @@ -226,11 +238,13 @@ static irqreturn_t smsm_intr(int irq, void *data) if (val & BIT(i)) { if (test_bit(i, entry->irq_rising)) { irq_pin = irq_find_mapping(entry->domain, i); + trace_smsm_irq_cascade(irq_pin, i, true); handle_nested_irq(irq_pin); } } else { if (test_bit(i, entry->irq_falling)) { irq_pin = irq_find_mapping(entry->domain, i); + trace_smsm_irq_cascade(irq_pin, i, false); handle_nested_irq(irq_pin); } } @@ -257,6 +271,7 @@ static void smsm_mask_irq(struct irq_data *irqd) val = readl(entry->subscription + smsm->local_host); val &= ~BIT(irq); writel(val, entry->subscription + smsm->local_host); + trace_smsm_irq_mask(irq, true, val); } clear_bit(irq, entry->irq_enabled); @@ -288,6 +303,7 @@ static void smsm_unmask_irq(struct irq_data *irqd) val = readl(entry->subscription + smsm->local_host); val |= BIT(irq); writel(val, entry->subscription + smsm->local_host); + trace_smsm_irq_mask(irq, false, val); } } diff --git a/drivers/soc/qcom/trace-smsm.h b/drivers/soc/qcom/trace-smsm.h new file mode 100644 index 0000000000000..8b8c79972130f --- /dev/null +++ b/drivers/soc/qcom/trace-smsm.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qcom_smsm + +#if !defined(__QCOM_SMSM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __QCOM_SMSM_TRACE_H__ + +#include +#include + +/* + * Fired on every call to smsm_update_bits(), whether or not the state + * actually changed. changes == 0 indicates the write was a no-op because + * the bits were already in the requested state. + */ +TRACE_EVENT(smsm_update_bits, + TP_PROTO(const struct device *dev, u32 mask, u32 value, + u32 orig, u32 val, u32 changes), + TP_ARGS(dev, mask, value, orig, val, changes), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u32, mask) + __field(u32, value) + __field(u32, orig) + __field(u32, val) + __field(u32, changes) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->mask = mask; + __entry->value = value; + __entry->orig = orig; + __entry->val = val; + __entry->changes = changes; + ), + TP_printk("%s: mask:0x%08x value:0x%08x 0x%08x->0x%08x changed:0x%08x", + __get_str(dev_name), + __entry->mask, __entry->value, + __entry->orig, __entry->val, + __entry->changes) +); + +/* + * Fired for each remote host that is subscribed to the changed bits and + * is about to receive an IPC kick. + */ +TRACE_EVENT(smsm_ipc_kick, + TP_PROTO(const struct device *dev, u32 host, u32 subscription), + TP_ARGS(dev, host, subscription), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u32, host) + __field(u32, subscription) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->host = host; + __entry->subscription = subscription; + ), + TP_printk("%s: kick host %u subscription:0x%08x", + __get_str(dev_name), __entry->host, __entry->subscription) +); + +/* + * Fired at the top of smsm_intr() after reading the remote state and + * computing the changed bits. + */ +TRACE_EVENT(smsm_intr, + TP_PROTO(int irq, u32 old_state, u32 new_state, u32 changed), + TP_ARGS(irq, old_state, new_state, changed), + TP_STRUCT__entry( + __field(int, irq) + __field(u32, old_state) + __field(u32, new_state) + __field(u32, changed) + ), + TP_fast_assign( + __entry->irq = irq; + __entry->old_state = old_state; + __entry->new_state = new_state; + __entry->changed = changed; + ), + TP_printk("IRQ %d: 0x%08x->0x%08x changed:0x%08x", + __entry->irq, + __entry->old_state, __entry->new_state, + __entry->changed) +); + +/* + * Fired for each cascaded (per-bit) IRQ that is about to be dispatched + * to a downstream consumer (e.g. the BAM DMUX pc/pc-ack handler). + */ +TRACE_EVENT(smsm_irq_cascade, + TP_PROTO(int irq_pin, unsigned int bit, bool rising), + TP_ARGS(irq_pin, bit, rising), + TP_STRUCT__entry( + __field(int, irq_pin) + __field(unsigned int, bit) + __field(bool, rising) + ), + TP_fast_assign( + __entry->irq_pin = irq_pin; + __entry->bit = bit; + __entry->rising = rising; + ), + TP_printk("IRQ %d bit %u %s", + __entry->irq_pin, __entry->bit, + __entry->rising ? "rising" : "falling") +); + +/* + * Fired when a cascaded per-bit IRQ is masked or unmasked, recording the + * resulting subscription bitmap written to shared memory. + */ +TRACE_EVENT(smsm_irq_mask, + TP_PROTO(unsigned long irq, bool mask, u32 subscription), + TP_ARGS(irq, mask, subscription), + TP_STRUCT__entry( + __field(unsigned long, irq) + __field(bool, mask) + __field(u32, subscription) + ), + TP_fast_assign( + __entry->irq = irq; + __entry->mask = mask; + __entry->subscription = subscription; + ), + TP_printk("IRQ %lu %s subscription:0x%08x", + __entry->irq, + __entry->mask ? "masked" : "unmasked", + __entry->subscription) +); + +#endif /* __QCOM_SMSM_TRACE_H__ */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace-smsm + +#include From f81f3c63ed0a6aae5a4b1c6714c0d81d973eb392 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Wed, 20 May 2026 15:46:36 +0530 Subject: [PATCH 0968/1058] net: wwan: qcom_bam_dmux: Add trace events Add ftrace tracepoints to the BAM-DMUX driver for observability of channel open/close (local and remote), RX callbacks, power on/off transitions, power control IRQs, and each step of the runtime resume sequence. Introduce a trace header and wire CFLAGS_qcom_bam_dmux.o so the trace header is found via -I$(src). Signed-off-by: Vishnu Santhosh --- drivers/net/wwan/Makefile | 1 + drivers/net/wwan/qcom_bam_dmux.c | 33 +++++- drivers/net/wwan/trace-bam-dmux.h | 169 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 drivers/net/wwan/trace-bam-dmux.h diff --git a/drivers/net/wwan/Makefile b/drivers/net/wwan/Makefile index 3960c0ae2445c..b6c6fc9ce0f5f 100644 --- a/drivers/net/wwan/Makefile +++ b/drivers/net/wwan/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_WWAN_HWSIM) += wwan_hwsim.o obj-$(CONFIG_MHI_WWAN_CTRL) += mhi_wwan_ctrl.o obj-$(CONFIG_MHI_WWAN_MBIM) += mhi_wwan_mbim.o +CFLAGS_qcom_bam_dmux.o := -I$(src) obj-$(CONFIG_QCOM_BAM_DMUX) += qcom_bam_dmux.o obj-$(CONFIG_RPMSG_WWAN_CTRL) += rpmsg_wwan_ctrl.o obj-$(CONFIG_IOSM) += iosm/ diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c index 6a5b22589af48..0d3865f612157 100644 --- a/drivers/net/wwan/qcom_bam_dmux.c +++ b/drivers/net/wwan/qcom_bam_dmux.c @@ -22,6 +22,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace-bam-dmux.h" + #define BAM_DMUX_BUFFER_SIZE SZ_2K #define BAM_DMUX_HDR_SIZE sizeof(struct bam_dmux_hdr) #define BAM_DMUX_MAX_DATA_SIZE (BAM_DMUX_BUFFER_SIZE - BAM_DMUX_HDR_SIZE) @@ -278,6 +281,7 @@ static int bam_dmux_netdev_open(struct net_device *netdev) struct bam_dmux_netdev *bndev = netdev_priv(netdev); int ret; + trace_bam_dmux_channel(bndev->dmux->dev, bndev->ch, "local_open"); ret = bam_dmux_send_cmd(bndev, BAM_DMUX_CMD_OPEN); if (ret) return ret; @@ -290,6 +294,7 @@ static int bam_dmux_netdev_stop(struct net_device *netdev) { struct bam_dmux_netdev *bndev = netdev_priv(netdev); + trace_bam_dmux_channel(bndev->dmux->dev, bndev->ch, "local_close"); netif_stop_queue(netdev); bam_dmux_send_cmd(bndev, BAM_DMUX_CMD_CLOSE); return 0; @@ -542,6 +547,7 @@ static void bam_dmux_cmd_open(struct bam_dmux *dmux, struct bam_dmux_hdr *hdr) struct net_device *netdev = dmux->netdevs[hdr->ch]; dev_dbg(dmux->dev, "open channel: %u\n", hdr->ch); + trace_bam_dmux_channel(dmux->dev, hdr->ch, "remote_open"); if (__test_and_set_bit(hdr->ch, dmux->remote_channels)) { dev_warn(dmux->dev, "Channel already open: %u\n", hdr->ch); @@ -561,6 +567,7 @@ static void bam_dmux_cmd_close(struct bam_dmux *dmux, struct bam_dmux_hdr *hdr) struct net_device *netdev = dmux->netdevs[hdr->ch]; dev_dbg(dmux->dev, "close channel: %u\n", hdr->ch); + trace_bam_dmux_channel(dmux->dev, hdr->ch, "remote_close"); if (!__test_and_clear_bit(hdr->ch, dmux->remote_channels)) { dev_err(dmux->dev, "Channel not open: %u\n", hdr->ch); @@ -590,6 +597,8 @@ static void bam_dmux_rx_callback(void *data) goto out; } + trace_bam_dmux_rx(dmux->dev, hdr->ch, hdr->cmd, hdr->len); + switch (hdr->cmd) { case BAM_DMUX_CMD_DATA: bam_dmux_cmd_data(skb_dma); @@ -624,16 +633,20 @@ static bool bam_dmux_power_on(struct bam_dmux *dmux) if (IS_ERR(dmux->rx)) { dev_err(dev, "Failed to request RX DMA channel: %pe\n", dmux->rx); dmux->rx = NULL; + trace_bam_dmux_power(dev, true, false); return false; } dmaengine_slave_config(dmux->rx, &dma_rx_conf); for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { - if (!bam_dmux_skb_dma_queue_rx(&dmux->rx_skbs[i], GFP_KERNEL)) + if (!bam_dmux_skb_dma_queue_rx(&dmux->rx_skbs[i], GFP_KERNEL)) { + trace_bam_dmux_power(dev, true, false); return false; + } } dma_async_issue_pending(dmux->rx); + trace_bam_dmux_power(dev, true, true); return true; } @@ -669,6 +682,7 @@ static void bam_dmux_power_off(struct bam_dmux *dmux) } bam_dmux_free_skbs(dmux->rx_skbs, DMA_FROM_DEVICE); + trace_bam_dmux_power(dmux->dev, false, true); } static irqreturn_t bam_dmux_pc_irq(int irq, void *data) @@ -677,6 +691,7 @@ static irqreturn_t bam_dmux_pc_irq(int irq, void *data) bool new_state = !dmux->pc_state; dev_dbg(dmux->dev, "pc: %u\n", new_state); + trace_bam_dmux_pc(dmux->dev, dmux->pc_state, new_state); if (new_state) { if (bam_dmux_power_on(dmux)) @@ -722,8 +737,11 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) /* Wait until previous power down was acked */ if (!wait_for_completion_timeout(&dmux->pc_ack_completion, - BAM_DMUX_REMOTE_TIMEOUT)) + BAM_DMUX_REMOTE_TIMEOUT)) { + trace_bam_dmux_resume_step(dev, "prev_ack", -ETIMEDOUT); return -ETIMEDOUT; + } + trace_bam_dmux_resume_step(dev, "prev_ack", 0); /* Vote for power state */ bam_dmux_pc_vote(dmux, true); @@ -732,33 +750,42 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) if (!wait_for_completion_timeout(&dmux->pc_ack_completion, BAM_DMUX_REMOTE_TIMEOUT)) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "ack", -ETIMEDOUT); return -ETIMEDOUT; } + trace_bam_dmux_resume_step(dev, "ack", 0); /* Wait until we're up */ if (!wait_event_timeout(dmux->pc_wait, dmux->pc_state, BAM_DMUX_REMOTE_TIMEOUT)) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "bam_up", -ETIMEDOUT); return -ETIMEDOUT; } + trace_bam_dmux_resume_step(dev, "bam_up", 0); /* Ensure that we actually initialized successfully */ if (!dmux->rx) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "bam_up", -ENXIO); return -ENXIO; } /* Request TX channel if necessary */ - if (dmux->tx) + if (dmux->tx) { + trace_bam_dmux_resume_step(dev, "tx_chan", 0); return 0; + } dmux->tx = dma_request_chan(dev, "tx"); if (IS_ERR(dmux->tx)) { dev_err(dev, "Failed to request TX DMA channel: %pe\n", dmux->tx); dmux->tx = NULL; bam_dmux_runtime_suspend(dev); + trace_bam_dmux_resume_step(dev, "tx_chan", -ENXIO); return -ENXIO; } + trace_bam_dmux_resume_step(dev, "tx_chan", 0); return 0; } diff --git a/drivers/net/wwan/trace-bam-dmux.h b/drivers/net/wwan/trace-bam-dmux.h new file mode 100644 index 0000000000000..b9a2b4b534e79 --- /dev/null +++ b/drivers/net/wwan/trace-bam-dmux.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qcom_bam_dmux + +#if !defined(__QCOM_BAM_DMUX_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __QCOM_BAM_DMUX_TRACE_H__ + +#include +#include + +/* + * Fired at the top of bam_dmux_pc_irq() when the modem toggles its BAM + * power-control SMSM bit. + * old_state: dmux->pc_state before the edge (0 = BAM was off) + * new_state: !old_state (what we are transitioning to) + * + * Downstream equivalent (BAM_DMUX_LOG): + * "bam_dmux_smsm_cb: 0x%08x -> 0x%08x" + "reconnect / disconnect / init" + */ +TRACE_EVENT(bam_dmux_pc, + TP_PROTO(const struct device *dev, bool old_state, bool new_state), + TP_ARGS(dev, old_state, new_state), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(bool, old_state) + __field(bool, new_state) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->old_state = old_state; + __entry->new_state = new_state; + ), + TP_printk("%s: pc %s -> %s", + __get_str(dev_name), + __entry->old_state ? "on" : "off", + __entry->new_state ? "on" : "off") +); + +/* + * Fired at the end of bam_dmux_power_on() and bam_dmux_power_off() to + * record whether the BAM DMA channel setup/teardown succeeded. + * on: true = power_on, false = power_off + * success: only meaningful when on=true; false means DMA channel + * request or RX buffer queueing failed + * + * Downstream equivalent: + * "reconnect_to_bam: disconnect tx/rx, device reset, sps_connect tx/rx" + * "disconnect_to_bam: disconnect tx, disconnect rx, device reset" + */ +TRACE_EVENT(bam_dmux_power, + TP_PROTO(const struct device *dev, bool on, bool success), + TP_ARGS(dev, on, success), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(bool, on) + __field(bool, success) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->on = on; + __entry->success = success; + ), + TP_printk("%s: power %s%s", + __get_str(dev_name), + __entry->on ? "on" : "off", + __entry->on ? (__entry->success ? " ok" : " failed") : "") +); + +/* + * Fired at the completion of each step inside bam_dmux_runtime_resume(). + * result=0 means the step passed; negative errno means it failed/timed out. + * + * Steps in order: + * "prev_ack" - waited for previous power-down to be acked by modem + * "ack" - voted for power and waited for modem's ack + * "bam_up" - waited for modem to signal BAM is powered (pc_state=true) + * "tx_chan" - requested TX DMA channel + * + * Downstream equivalent (BAM_DMUX_LOG): + * "ul_wakeup waiting for previous ack" + * "ul_wakeup waiting for wakeup ack" + * "ul_wakeup waiting completion" + * "ul_wakeup complete" + */ +TRACE_EVENT(bam_dmux_resume_step, + TP_PROTO(const struct device *dev, const char *step, int result), + TP_ARGS(dev, step, result), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __string(step, step) + __field(int, result) + ), + TP_fast_assign( + __assign_str(dev_name); + __assign_str(step); + __entry->result = result; + ), + TP_printk("%s: resume %s: %d", + __get_str(dev_name), __get_str(step), __entry->result) +); + +/* + * Fired on every channel open and close event, from both the modem side + * (CMD_OPEN/CMD_CLOSE) and the local netdev side (ndo_open/ndo_stop). + * + * event: "remote_open" - modem sent CMD_OPEN + * "remote_close" - modem sent CMD_CLOSE + * "local_open" - AP opened the netdev (sent CMD_OPEN to modem) + * "local_close" - AP stopped the netdev (sent CMD_CLOSE to modem) + * + * Downstream equivalent (BAM_DMUX_LOG / BAM_DMUX_INFO): + * "handle_bam_mux_cmd: opening cid N PC enabled" + * "msm_bam_dmux_open: opening/opened ch N" + * "msm_bam_dmux_close: closing/closed ch N" + */ +TRACE_EVENT(bam_dmux_channel, + TP_PROTO(const struct device *dev, u8 ch, const char *event), + TP_ARGS(dev, ch, event), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u8, ch) + __string(event, event) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->ch = ch; + __assign_str(event); + ), + TP_printk("%s: ch %u %s", + __get_str(dev_name), __entry->ch, __get_str(event)) +); + +/* + * Fired in bam_dmux_rx_callback() for every valid inbound packet after + * magic and channel validation. For data packets, len is the payload + * length. For control packets (OPEN/CLOSE), len is 0. + * + * Downstream equivalent (BAM_DMUX_INFO via handle_bam_mux_cmd): + * "handle_bam_mux_cmd: magic 33fc signal %x cmd %d pad %d ch %d len %d" + */ +TRACE_EVENT(bam_dmux_rx, + TP_PROTO(const struct device *dev, u8 ch, u8 cmd, u16 len), + TP_ARGS(dev, ch, cmd, len), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u8, ch) + __field(u8, cmd) + __field(u16, len) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->ch = ch; + __entry->cmd = cmd; + __entry->len = len; + ), + TP_printk("%s: rx ch %u cmd %u len %u", + __get_str(dev_name), __entry->ch, __entry->cmd, __entry->len) +); + +#endif /* __QCOM_BAM_DMUX_TRACE_H__ */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace-bam-dmux + +#include From 96d1cfec419efdae399174f28c000705455146a4 Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Fri, 8 May 2026 21:40:09 +0800 Subject: [PATCH 0969/1058] drm/bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: - LT9611C: supports 1-port mipi dsi to hdmi 1.4 - LT9611EX: supports 2-port mipi dsi to hdmi 1.4 - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0 Link : https://lore.kernel.org/lkml/20260508134009.4582-3-syyang@lontium.com/ Signed-off-by: Sunyun Yang Reviewed-by: Dmitry Baryshkov Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/Kconfig | 18 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/lontium-lt9611c.c | 1241 ++++++++++++++++++++++ 3 files changed, 1260 insertions(+) create mode 100644 drivers/gpu/drm/bridge/lontium-lt9611c.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 4a57d49b4c6d3..b8959b8e2ad05 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -177,6 +177,24 @@ config DRM_LONTIUM_LT9611 HDMI signals Please say Y if you have such hardware. +config DRM_LONTIUM_LT9611C + tristate "Lontium LT9611C DSI/HDMI bridge" + select SND_SOC_HDMI_CODEC if SND_SOC + depends on OF + select CRC8 + select FW_LOADER + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select REGMAP_I2C + help + Driver for Lontium DSI to HDMI bridge + chip driver that converts dual DSI and I2S to + HDMI signals + Please say Y if you have such hardware. + config DRM_LONTIUM_LT9611UXC tristate "Lontium LT9611UXC DSI/HDMI bridge" select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 15cc821d85b7e..f322f3f89f6bf 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o +obj-$(CONFIG_DRM_LONTIUM_LT9611C) += lontium-lt9611c.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o obj-$(CONFIG_DRM_LONTIUM_LT8713SX) += lontium-lt8713sx.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c new file mode 100644 index 0000000000000..cb584855fd8f0 --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -0,0 +1,1241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 Lontium Semiconductor, Inc. + */ + +#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 + +#define FW_SIZE (64 * 1024) +#define LT_PAGE_SIZE 256 +#define FW_FILE "Lontium/lt9611c_fw.bin" +#define LT9611C_CRC_POLYNOMIAL 0x31 +#define LT9611C_PAGE_CONTROL 0xff + +enum lt9611_chip_type { + CHIP_LT9611C = 0, + CHIP_LT9611EX, + CHIP_LT9611UXD, +}; + +struct lt9611c { + struct device *dev; + struct i2c_client *client; + struct drm_bridge bridge; + struct regmap *regmap; + /* Protects all accesses to registers by stopping the on-chip MCU */ + struct mutex ocm_lock; + struct work_struct work; + struct device_node *dsi0_node; + struct device_node *dsi1_node; + struct mipi_dsi_device *dsi0; + struct mipi_dsi_device *dsi1; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[2]; + int fw_version; + /* Chip variant: C/EX/UXD */ + enum lt9611_chip_type chip_type; + /* HDMI cable connection status */ + bool hdmi_connected; +}; + +DECLARE_CRC8_TABLE(lt9611c_crc8_table); + +static const struct regmap_range_cfg lt9611c_ranges[] = { + { + .name = "register_range", + .range_min = 0, + .range_max = 0xfe9c, + .selector_reg = LT9611C_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config lt9611c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xfe9c, + .ranges = lt9611c_ranges, + .num_ranges = ARRAY_SIZE(lt9611c_ranges), +}; + +static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, + unsigned int param_count, u8 *return_buffer, + unsigned int return_count) +{ + int ret; + unsigned int i; + unsigned int temp; + unsigned int max_params = 0xe0dd - 0xe0b0 + 1; + + regmap_write(lt9611c->regmap, 0xe0de, 0x01); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x01, 1000, 100 * 1000); + if (ret) + return -ETIMEDOUT; + + for (i = 0; i < param_count && i < max_params; i++) + regmap_write(lt9611c->regmap, 0xe0b0 + i, params[i]); + + regmap_write(lt9611c->regmap, 0xe0de, 0x02); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x02, 1000, 100 * 1000); + if (ret) + return -ETIMEDOUT; + + return regmap_bulk_read(lt9611c->regmap, 0xe085, return_buffer, + return_count); +} + +static void lt9611c_config_parameters(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write_paras[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe103, 0x3f), /*fifo rst*/ + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0xc1), + REG_SEQ0(0xe058, 0x00), + REG_SEQ0(0xe059, 0x50), + REG_SEQ0(0xe05a, 0x10), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write_paras, ARRAY_SIZE(seq_write_paras)); +} + +static void lt9611c_wren(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x04); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_wrdi(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x08); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_erase_op(struct lt9611c *lt9611c, u32 addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe05a, 0x04), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x01), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void read_flash_reg_status(struct lt9611c *lt9611c, unsigned int *status) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe103, 0x3f), + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0x40), + REG_SEQ0(0xe056, 0x05), + REG_SEQ0(0xe055, 0x25), + REG_SEQ0(0xe055, 0x01), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); + + regmap_read(lt9611c->regmap, 0xe05f, status); +} + +static void lt9611c_crc_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0x00), + REG_SEQ0(0xe055, 0xc0), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_data_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0xff), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_sram_to_flash(struct lt9611c *lt9611c, size_t addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x30), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_block_erase(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int i; + unsigned int block_num; + unsigned int flash_status = 0; + u32 flash_addr = 0; + + for (block_num = 0; block_num < 2; block_num++) { + flash_addr = (block_num * 0x008000); + lt9611c_erase_op(lt9611c, flash_addr); + msleep(100); + i = 0; + while (1) { + read_flash_reg_status(lt9611c, &flash_status); + if ((flash_status & 0x01) == 0) + break; + + if (i > 50) + break; + + i++; + msleep(50); + } + } + + dev_dbg(dev, "erase flash done.\n"); +} + +static int lt9611c_write_data(struct lt9611c *lt9611c, const struct firmware *fw, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + unsigned int page = 0, num = 0, i = 0; + size_t size, index; + const u8 *data; + u8 value; + + data = fw->data; + size = fw->size; + page = (size + LT_PAGE_SIZE - 1) / LT_PAGE_SIZE; + if (page * LT_PAGE_SIZE > FW_SIZE) { + dev_err(dev, "firmware size out of range\n"); + return -EINVAL; + } + + dev_dbg(dev, "%u pages, total size %zu byte\n", page, size); + + for (num = 0; num < page; num++) { + lt9611c_data_to_sram(lt9611c); + + for (i = 0; i < LT_PAGE_SIZE; i++) { + index = num * LT_PAGE_SIZE + i; + value = (index < size) ? data[index] : 0xff; + + ret = regmap_write(lt9611c->regmap, 0xe059, value); + if (ret < 0) { + dev_err(dev, "write error at page %u, index %u\n", num, i); + return ret; + } + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + + addr += LT_PAGE_SIZE; + } + + lt9611c_wrdi(lt9611c); + + return 0; +} + +static int lt9611c_write_crc(struct lt9611c *lt9611c, u8 fw_crc, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c_crc_to_sram(lt9611c); + ret = regmap_write(lt9611c->regmap, 0xe059, fw_crc); + if (ret < 0) { + dev_err(dev, "failed to write crc\n"); + return ret; + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + lt9611c_wrdi(lt9611c); + + dev_dbg(dev, "crc 0x%02x written to flash at addr 0x%zx\n", fw_crc, addr); + + return 0; +} + +static void lt9611c_reset(struct lt9611c *lt9611c) +{ + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(400); + + dev_dbg(lt9611c->dev, "lt9611c reset"); +} + +static int lt9611c_upgrade_result(struct lt9611c *lt9611c, u8 fw_crc) +{ + struct device *dev = lt9611c->dev; + unsigned int crc_result; + + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + regmap_read(lt9611c->regmap, 0xe021, &crc_result); + + if (crc_result != fw_crc) { + dev_err(dev, "lt9611c fw upgrade failed, expected crc=0x%02x, read crc=0x%02x\n", + fw_crc, crc_result); + return -1; + } + + dev_dbg(dev, "lt9611c firmware upgrade success, crc=0x%02x\n", crc_result); + return 0; +} + +static int lt9611c_firmware_upgrade(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + const struct firmware *fw; + u8 *buffer; + size_t total_size = FW_SIZE - 1; + u8 fw_crc; + int ret; + + /* 1. load firmware */ + ret = request_firmware(&fw, FW_FILE, dev); + if (ret) + return dev_err_probe(dev, ret, "failed to load '%s'\n", FW_FILE); + + /* 2. check size */ + if (fw->size > total_size) { + dev_err(dev, "firmware too large (%zu > %zu)\n", fw->size, total_size); + ret = -EINVAL; + goto out_release_fw; + } + dev_dbg(dev, "firmware size: %zu bytes\n", fw->size); + + /* 3. calculate crc8 */ + buffer = kzalloc(total_size, GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto out_release_fw; + } + + memset(buffer, 0xff, total_size); + memcpy(buffer, fw->data, fw->size); + + fw_crc = crc8(lt9611c_crc8_table, buffer, total_size, 0); + kfree(buffer); + + dev_dbg(dev, "firmware crc: 0x%02x\n", fw_crc); + dev_dbg(dev, "starting firmware upgrade, size: %zu bytes\n", fw->size); + + /* 4. firmware upgrade */ + lt9611c_config_parameters(lt9611c); + lt9611c_block_erase(lt9611c); + + ret = lt9611c_write_data(lt9611c, fw, 0); + if (ret < 0) { + dev_err(dev, "failed to write firmware data\n"); + goto out_release_fw; + } + + ret = lt9611c_write_crc(lt9611c, fw_crc, FW_SIZE - 1); + if (ret < 0) { + dev_err(dev, "failed to write firmware crc\n"); + goto out_release_fw; + } + + /* 5. check upgrade of result */ + lt9611c_reset(lt9611c); + ret = lt9611c_upgrade_result(lt9611c, fw_crc); + +out_release_fw: + release_firmware(fw); + return ret; +} + +static struct lt9611c *bridge_to_lt9611c(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9611c, bridge); +} + +/*read only*/ +static const struct lt9611c *bridge_to_lt9611c_const(const struct drm_bridge *bridge) +{ + return container_of(bridge, const struct lt9611c, bridge); +} + +static void lt9611c_lock(struct lt9611c *lt9611c) +{ + mutex_lock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); +} + +static void lt9611c_unlock(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + mutex_unlock(<9611c->ocm_lock); +} + +static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) +{ + struct lt9611c *lt9611c = dev_id; + struct device *dev = lt9611c->dev; + int ret; + unsigned int irq_status; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); + if (ret) { + dev_err(dev, "failed to read irq status: %d\n", ret); + return IRQ_HANDLED; + } + + if (!(irq_status & BIT(0))) + return IRQ_HANDLED; + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) { + dev_err(dev, "failed to read HPD status\n"); + } else { + lt9611c->hdmi_connected = (data[4] == 0x02); + dev_dbg(dev, "HDMI %s\n", lt9611c->hdmi_connected ? "connected" : "disconnected"); + } + + /*Clear interrupt: hardware requires two writes with delay*/ + regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); + usleep_range(10000, 12000); + regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); + + schedule_work(<9611c->work); + + return IRQ_HANDLED; +} + +static void lt9611c_hpd_work(struct work_struct *work) +{ + struct lt9611c *lt9611c = container_of(work, struct lt9611c, work); + bool connected; + + mutex_lock(<9611c->ocm_lock); + connected = lt9611c->hdmi_connected; + mutex_unlock(<9611c->ocm_lock); + + drm_bridge_hpd_notify(<9611c->bridge, + connected ? connector_status_connected : + connector_status_disconnected); +} + +static int lt9611c_regulator_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c->supplies[0].supply = "vcc"; + lt9611c->supplies[1].supply = "vdd"; + + ret = devm_regulator_bulk_get(dev, 2, lt9611c->supplies); + + return ret; +} + +static struct mipi_dsi_device *lt9611c_attach_dsi(struct lt9611c *lt9611c, + struct device_node *dsi_node) +{ + const struct mipi_dsi_device_info info = { "lt9611c", 0, NULL }; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + struct device *dev = lt9611c->dev; + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n")); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE; + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) + return ERR_PTR(dev_err_probe(dev, ret, "failed to attach dsi to host\n")); + + return dsi; +} + +static int lt9611c_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, + enum drm_bridge_attach_flags flags) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_bridge_attach(encoder, lt9611c->bridge.next_bridge, bridge, flags); +} + +static enum drm_mode_status +lt9611c_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + const struct lt9611c *lt9611c = bridge_to_lt9611c_const(bridge); + + if (lt9611c->chip_type == CHIP_LT9611UXD) { + if (tmds_rate > 600000000) + return MODE_CLOCK_HIGH; + + } else { + if (tmds_rate > 340000000) + return MODE_CLOCK_HIGH; + } + + if (tmds_rate < 25000000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static void lt9611c_video_setup(struct lt9611c *lt9611c, + const struct drm_display_mode *mode) +{ + struct device *dev = lt9611c->dev; + int ret; + u32 h_total, hactive, hsync_len, hfront_porch, hback_porch; + u32 v_total, vactive, vsync_len, vfront_porch, vback_porch; + u8 timing_set_cmd[26] = {0x57, 0x4d, 0x33, 0x3a}; + u8 return_param[3]; + u8 framerate; + u8 vic = 0x00; + + guard(mutex)(<9611c->ocm_lock); + h_total = mode->htotal; + hactive = mode->hdisplay; + hsync_len = mode->hsync_end - mode->hsync_start; + hfront_porch = mode->hsync_start - mode->hdisplay; + hback_porch = mode->htotal - mode->hsync_end; + + v_total = mode->vtotal; + vactive = mode->vdisplay; + vsync_len = mode->vsync_end - mode->vsync_start; + vfront_porch = mode->vsync_start - mode->vdisplay; + vback_porch = mode->vtotal - mode->vsync_end; + framerate = drm_mode_vrefresh(mode); + vic = drm_match_cea_mode(mode); + + dev_dbg(dev, "hactive=%d, vactive=%d\n", hactive, vactive); + dev_dbg(dev, "framerate=%d\n", framerate); + dev_dbg(dev, "vic = 0x%02x\n", vic); + + timing_set_cmd[4] = (h_total >> 8) & 0xff; + timing_set_cmd[5] = h_total & 0xff; + timing_set_cmd[6] = (hactive >> 8) & 0xff; + timing_set_cmd[7] = hactive & 0xff; + timing_set_cmd[8] = (hfront_porch >> 8) & 0xff; + timing_set_cmd[9] = hfront_porch & 0xff; + timing_set_cmd[10] = (hsync_len >> 8) & 0xff; + timing_set_cmd[11] = hsync_len & 0xff; + timing_set_cmd[12] = (hback_porch >> 8) & 0xff; + timing_set_cmd[13] = hback_porch & 0xff; + timing_set_cmd[14] = (v_total >> 8) & 0xff; + timing_set_cmd[15] = v_total & 0xff; + timing_set_cmd[16] = (vactive >> 8) & 0xff; + timing_set_cmd[17] = vactive & 0xFF; + timing_set_cmd[18] = (vfront_porch >> 8) & 0xff; + timing_set_cmd[19] = vfront_porch & 0xff; + timing_set_cmd[20] = (vsync_len >> 8) & 0xff; + timing_set_cmd[21] = vsync_len & 0xff; + timing_set_cmd[22] = (vback_porch >> 8) & 0xff; + timing_set_cmd[23] = vback_porch & 0xff; + timing_set_cmd[24] = framerate; + timing_set_cmd[25] = vic; + + ret = lt9611c_read_write_flow(lt9611c, + timing_set_cmd, ARRAY_SIZE(timing_set_cmd), + return_param, ARRAY_SIZE(return_param)); + if (ret) + dev_err(dev, "video set failed\n"); +} + +static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + lt9611c_reset(lt9611c); +} + +static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *mode; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + mode = &crtc_state->adjusted_mode; + + lt9611c_video_setup(lt9611c, mode); +} + +static void lt9611c_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); +} + +static enum drm_connector_status +lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct device *dev = lt9611c->dev; + int ret; + bool connected = false; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) + dev_err(dev, "failed to read HPD status (err=%d)\n", ret); + else + connected = (data[4] == 0x02); + + lt9611c->hdmi_connected = connected; + + return connected ? connector_status_connected : + connector_status_disconnected; +} + +static int lt9611c_get_edid_block(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct lt9611c *lt9611c = data; + struct device *dev = lt9611c->dev; + u8 cmd[5] = {0x52, 0x48, 0x33, 0x3a, 0x00}; + u8 packet[37]; + int ret, i, offset = 0; + + if (len != 128) + return -EINVAL; + guard(mutex)(<9611c->ocm_lock); + + for (i = 0; i < 4; i++) { + cmd[4] = block * 4 + i; + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + packet, ARRAY_SIZE(packet)); + if (ret) { + dev_err(dev, "Failed to read EDID block %u packet %d\n", + block, i); + return ret; + } + memcpy(buf + offset, &packet[5], 32); + offset += 32; + } + + return 0; +} + +static const struct drm_edid *lt9611c_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_edid_read_custom(connector, lt9611c_get_edid_block, lt9611c); +} + +static int lt9611c_hdmi_write_avi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x01;/*write avi*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x01}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x02;/*write audio*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_audio_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x02}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 audio_cmd[6] = {0x57, 0x48, 0x36, 0x3a}; + u8 data[5]; + int ret; + + if (hparms->sample_width == 32) + return -EINVAL; + + switch (fmt->fmt) { + case HDMI_I2S: + audio_cmd[4] = 0x01; + break; + case HDMI_SPDIF: + audio_cmd[4] = 0x02; + break; + default: + return -EINVAL; + } + + audio_cmd[5] = hparms->channels; + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, audio_cmd, sizeof(audio_cmd), + data, sizeof(data)); + if (ret < 0) { + dev_err(lt9611c->dev, "set audio info failed!\n"); + return ret; + } + + return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + &hparms->cea); +} + +static void lt9611c_hdmi_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); +} + +static int lt9611c_hdmi_audio_startup(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + return 0; +} + +static const struct drm_bridge_funcs lt9611c_bridge_funcs = { + .attach = lt9611c_bridge_attach, + .detect = lt9611c_bridge_detect, + .edid_read = lt9611c_bridge_edid_read, + .atomic_pre_enable = lt9611c_bridge_atomic_pre_enable, + .atomic_enable = lt9611c_bridge_atomic_enable, + .atomic_post_disable = lt9611c_bridge_atomic_post_disable, + .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, + + .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, + .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, + .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, + .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, + + .hdmi_audio_startup = lt9611c_hdmi_audio_startup, + .hdmi_audio_prepare = lt9611c_hdmi_audio_prepare, + .hdmi_audio_shutdown = lt9611c_hdmi_audio_shutdown, +}; + +static int lt9611c_parse_dt(struct device *dev, + struct lt9611c *lt9611c) +{ + lt9611c->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); + if (!lt9611c->dsi0_node) + return dev_err_probe(dev, -ENODEV, "failed to get remote node for primary dsi\n"); + + lt9611c->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + + return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); +} + +static int lt9611c_gpio_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + + lt9611c->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(lt9611c->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(lt9611c->reset_gpio), + "failed to acquire reset gpio\n"); + + return 0; +} + +static int lt9611c_read_version(struct lt9611c *lt9611c) +{ + u8 buf[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe080, buf, ARRAY_SIZE(buf)); + if (ret) + return ret; + + return (buf[0] << 8) | buf[1]; +} + +static int lt9611c_read_chipid(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + u8 chipid[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe100, chipid, 2); + if (ret) + return ret; + + if (chipid[0] != 0x23 || chipid[1] != 0x06) { + dev_err(dev, "ChipID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + return -ENODEV; + } + + return 0; +} + +static ssize_t lt9611c_firmware_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + lt9611c_lock(lt9611c); + + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) + dev_err(dev, "upgrade failure\n"); + + lt9611c_unlock(lt9611c); + + return ret < 0 ? ret : len; +} + +static ssize_t lt9611c_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%04x\n", lt9611c->fw_version); +} + +static DEVICE_ATTR_RW(lt9611c_firmware); + +static struct attribute *lt9611c_attrs[] = { + &dev_attr_lt9611c_firmware.attr, + NULL, +}; + +static const struct attribute_group lt9611c_attr_group = { + .attrs = lt9611c_attrs, +}; + +static const struct attribute_group *lt9611c_attr_groups[] = { + <9611c_attr_group, + NULL, +}; + +static int lt9611c_probe(struct i2c_client *client) +{ + const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct lt9611c *lt9611c; + struct device *dev = &client->dev; + bool fw_updated = false; + int ret; + + crc8_populate_msb(lt9611c_crc8_table, LT9611C_CRC_POLYNOMIAL); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return dev_err_probe(dev, -ENODEV, "device doesn't support I2C\n"); + + lt9611c = devm_drm_bridge_alloc(dev, struct lt9611c, bridge, <9611c_bridge_funcs); + if (IS_ERR(lt9611c)) + return dev_err_probe(dev, PTR_ERR(lt9611c), "drm bridge alloc failed.\n"); + + lt9611c->dev = dev; + lt9611c->client = client; + lt9611c->chip_type = id->driver_data; + ret = devm_mutex_init(dev, <9611c->ocm_lock); + if (ret) + return dev_err_probe(dev, ret, "failed to init mutex\n"); + + lt9611c->regmap = devm_regmap_init_i2c(client, <9611c_regmap_config); + if (IS_ERR(lt9611c->regmap)) + return dev_err_probe(dev, PTR_ERR(lt9611c->regmap), "regmap i2c init failed\n"); + + ret = lt9611c_parse_dt(dev, lt9611c); + if (ret) + return dev_err_probe(dev, ret, "failed to parse device tree\n"); + + ret = lt9611c_gpio_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = lt9611c_regulator_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + goto err_of_put; + + lt9611c_reset(lt9611c); + + lt9611c_lock(lt9611c); + + ret = lt9611c_read_chipid(lt9611c); + if (ret < 0) { + dev_err(dev, "failed to read chip id.\n"); + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + +retry: + lt9611c->fw_version = lt9611c_read_version(lt9611c); + if (lt9611c->fw_version < 0) { + dev_err(dev, "failed to read fw version\n"); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + + } else if (lt9611c->fw_version == 0) { + if (!fw_updated) { + fw_updated = true; + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) { + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + + goto retry; + + } else { + dev_err(dev, "fw version 0x%04x, update failed\n", lt9611c->fw_version); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + } + + lt9611c_unlock(lt9611c); + dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); + + INIT_WORK(<9611c->work, lt9611c_hpd_work); + + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + lt9611c_irq_thread_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT | + IRQF_NO_AUTOEN, + "lt9611c", lt9611c); + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto err_disable_regulators; + } + + lt9611c->bridge.of_node = client->dev.of_node; + lt9611c->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO; + lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + + lt9611c->bridge.hdmi_audio_dev = dev; + lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; + lt9611c->bridge.hdmi_audio_dai_port = 2; + + devm_drm_bridge_add(dev, <9611c->bridge); + + /* Attach primary DSI */ + lt9611c->dsi0 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi0_node); + if (IS_ERR(lt9611c->dsi0)) { + ret = PTR_ERR(lt9611c->dsi0); + goto err_remove_bridge; + } + + /* Attach secondary DSI, if specified */ + if (lt9611c->dsi1_node) { + lt9611c->dsi1 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi1_node); + if (IS_ERR(lt9611c->dsi1)) { + ret = PTR_ERR(lt9611c->dsi1); + goto err_remove_bridge; + } + } + + lt9611c->hdmi_connected = false; + i2c_set_clientdata(client, lt9611c); + enable_irq(client->irq); + lt9611c_reset(lt9611c); + + return 0; + +err_remove_bridge: + free_irq(client->irq, lt9611c); + cancel_work_sync(<9611c->work); + drm_bridge_remove(<9611c->bridge); + +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + +err_of_put: + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); + + return ret; +} + +static void lt9611c_remove(struct i2c_client *client) +{ + struct lt9611c *lt9611c = i2c_get_clientdata(client); + + free_irq(client->irq, lt9611c); + cancel_work_sync(<9611c->work); + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); +} + +static int lt9611c_bridge_suspend(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + dev_dbg(lt9611c->dev, "suspend\n"); + disable_irq(lt9611c->client->irq); + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + return ret; + } + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + + return ret; +} + +static int lt9611c_bridge_resume(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + return ret; + } + enable_irq(lt9611c->client->irq); + lt9611c_reset(lt9611c); + dev_dbg(lt9611c->dev, "resume\n"); + + return ret; +} + +static const struct dev_pm_ops lt9611c_bridge_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(lt9611c_bridge_suspend, + lt9611c_bridge_resume) +}; + +static struct i2c_device_id lt9611c_id[] = { + /* chip_type */ + { "lontium,lt9611c", 0 }, + { "lontium,lt9611ex", 1 }, + { "lontium,lt9611uxd", 2 }, + { /* sentinel */ } +}; + +static const struct of_device_id lt9611c_match_table[] = { + { .compatible = "lontium,lt9611c" }, + { .compatible = "lontium,lt9611ex" }, + { .compatible = "lontium,lt9611uxd" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lt9611c_match_table); + +static struct i2c_driver lt9611c_driver = { + .driver = { + .name = "lt9611c", + .of_match_table = lt9611c_match_table, + .pm = <9611c_bridge_pm_ops, + .dev_groups = lt9611c_attr_groups, + }, + .probe = lt9611c_probe, + .remove = lt9611c_remove, + .id_table = lt9611c_id, +}; +module_i2c_driver(lt9611c_driver); + +MODULE_AUTHOR("SunYun Yang "); +MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FW_FILE); + From 7b6584a8c81b823102c3a590174667925f2af098 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 28 May 2026 21:40:01 +0530 Subject: [PATCH 0970/1058] drm/bridge: Enable LT9611UXD in LT9611C driver Changes to enable lt9611uxd in lt9611c driver. Added support for port selection, enabled hdmi enable gpio and other changes. Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 280 ++++++++++++++++++----- 1 file changed, 228 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index cb584855fd8f0..4b83322493903 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -41,6 +41,13 @@ enum lt9611_chip_type { CHIP_LT9611UXD, }; +enum lt9611c_ports { + PORT_SWAP_A = 0, + PORT_SWAP_B, + PORT_SWAP_AB, + PORT_MAX, +}; + struct lt9611c { struct device *dev; struct i2c_client *client; @@ -54,12 +61,15 @@ struct lt9611c { struct mipi_dsi_device *dsi0; struct mipi_dsi_device *dsi1; struct gpio_desc *reset_gpio; + struct gpio_desc *hdmi_gpio; struct regulator_bulk_data supplies[2]; int fw_version; /* Chip variant: C/EX/UXD */ enum lt9611_chip_type chip_type; /* HDMI cable connection status */ bool hdmi_connected; + /* Selected DSI port configuration */ + int selected_port; }; DECLARE_CRC8_TABLE(lt9611c_crc8_table); @@ -97,7 +107,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x01); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x01, 1000, 100 * 1000); + temp == 0x01, 1000, 400 * 1000); if (ret) return -ETIMEDOUT; @@ -107,7 +117,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x02); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x02, 1000, 100 * 1000); + temp == 0x02, 1000, 400 * 1000); if (ret) return -ETIMEDOUT; @@ -115,6 +125,48 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, return_count); } +static int lt9611c_select_port(struct lt9611c *lt9611c, int port_select) +{ + int ret; + u8 set_port_swap_cmd_A[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0xc0}; + u8 set_port_swap_cmd_B[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0x40}; + u8 set_port_swap_cmd_AB[6] = {0x57, 0x4d, 0x31, 0x3a, 0x02, 0xd0}; + u8 set_port_swap_ret[5]; + + if (!lt9611c) + return -EINVAL; + + /* MCU must be running (0xe0ee=0x00) for lt9611c_read_write_flow */ + guard(mutex)(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + + switch (port_select) { + case PORT_SWAP_A: + ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_A, + 6, set_port_swap_ret, 5); + if (ret < 0 || set_port_swap_ret[4] == 0) + return ret < 0 ? ret : -EIO; + break; + + case PORT_SWAP_B: + ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_B, + 6, set_port_swap_ret, 5); + if (ret < 0 || set_port_swap_ret[4] == 0) + return ret < 0 ? ret : -EIO; + break; + + case PORT_SWAP_AB: + ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_AB, + 6, set_port_swap_ret, 5); + if (ret < 0 || set_port_swap_ret[4] == 0) + return ret < 0 ? ret : -EIO; + break; + default: + return -EINVAL; + } + return 0; +} + static void lt9611c_config_parameters(struct lt9611c *lt9611c) { const struct reg_sequence seq_write_paras[] = { @@ -436,16 +488,22 @@ static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; u8 data[5]; - guard(mutex)(<9611c->ocm_lock); + mutex_lock(<9611c->ocm_lock); + + /* Ensure MCU is running for HPD status query */ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); if (ret) { dev_err(dev, "failed to read irq status: %d\n", ret); + mutex_unlock(<9611c->ocm_lock); return IRQ_HANDLED; } - if (!(irq_status & BIT(0))) + if (!(irq_status & BIT(0))) { + mutex_unlock(<9611c->ocm_lock); return IRQ_HANDLED; + } ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); if (ret) { @@ -455,10 +513,11 @@ static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) dev_dbg(dev, "HDMI %s\n", lt9611c->hdmi_connected ? "connected" : "disconnected"); } - /*Clear interrupt: hardware requires two writes with delay*/ - regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); + regmap_write(lt9611c->regmap, 0xe0df, BIT(0)); usleep_range(10000, 12000); - regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); + regmap_write(lt9611c->regmap, 0xe0df, 0x00); + + mutex_unlock(<9611c->ocm_lock); schedule_work(<9611c->work); @@ -619,10 +678,20 @@ static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); int ret; - ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - if (ret) - dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); - lt9611c_reset(lt9611c); + if (lt9611c->hdmi_gpio) { + gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); + msleep(20); + } +// lt9611c_reset(lt9611c); + + /* Reapply port selection after reset */ + if (lt9611c->selected_port >= 0) { + msleep(200); + ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); + if (ret < 0) + dev_err(lt9611c->dev, "failed to reapply port selection: %d\n", ret); + msleep(200); + } } static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, @@ -655,12 +724,12 @@ static void lt9611c_bridge_atomic_post_disable(struct drm_bridge *bridge, struct drm_atomic_state *state) { struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); - int ret; - ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - if (ret) - dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); - gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + /* Keep chip active for HPD detection */ + mutex_lock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + regmap_write(lt9611c->regmap, 0xe0d0, 0x01); + mutex_unlock(<9611c->ocm_lock); } static enum drm_connector_status @@ -673,7 +742,10 @@ lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; u8 data[5]; - guard(mutex)(<9611c->ocm_lock); + mutex_lock(<9611c->ocm_lock); + + /* Ensure MCU is running for HPD status query */ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); if (ret) @@ -683,6 +755,8 @@ lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector lt9611c->hdmi_connected = connected; + mutex_unlock(<9611c->ocm_lock); + return connected ? connector_status_connected : connector_status_disconnected; } @@ -777,6 +851,59 @@ static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) return 0; } +static int lt9611c_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x03;/*write hdmi infoframe*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write hdmi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x03}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear hdmi infoframe failed!\n"); + return ret; + } + + return 0; +} + static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, const u8 *buffer, size_t len) { @@ -895,6 +1022,8 @@ static const struct drm_bridge_funcs lt9611c_bridge_funcs = { .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_hdmi_infoframe = lt9611c_hdmi_write_hdmi_infoframe, + .hdmi_clear_hdmi_infoframe = lt9611c_hdmi_clear_hdmi_infoframe, .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, @@ -924,6 +1053,11 @@ static int lt9611c_gpio_init(struct lt9611c *lt9611c) return dev_err_probe(dev, PTR_ERR(lt9611c->reset_gpio), "failed to acquire reset gpio\n"); + lt9611c->hdmi_gpio = devm_gpiod_get_optional(dev, "hdmi", GPIOD_OUT_LOW); + if (IS_ERR(lt9611c->hdmi_gpio)) + return dev_err_probe(dev, PTR_ERR(lt9611c->hdmi_gpio), + "failed to acquire hdmi gpio\n"); + return 0; } @@ -1007,7 +1141,6 @@ static const struct attribute_group *lt9611c_attr_groups[] = { static int lt9611c_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct lt9611c *lt9611c; struct device *dev = &client->dev; bool fw_updated = false; @@ -1024,7 +1157,7 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->dev = dev; lt9611c->client = client; - lt9611c->chip_type = id->driver_data; + lt9611c->chip_type = (enum lt9611_chip_type)(uintptr_t)of_device_get_match_data(dev); ret = devm_mutex_init(dev, <9611c->ocm_lock); if (ret) return dev_err_probe(dev, ret, "failed to init mutex\n"); @@ -1041,15 +1174,13 @@ static int lt9611c_probe(struct i2c_client *client) if (ret < 0) goto err_of_put; - ret = lt9611c_regulator_init(lt9611c); - if (ret < 0) - goto err_of_put; - - ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - if (ret) - goto err_of_put; + if (lt9611c->hdmi_gpio) { + gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); + msleep(20); + } lt9611c_reset(lt9611c); + msleep(300); lt9611c_lock(lt9611c); @@ -1076,7 +1207,6 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c_unlock(lt9611c); goto err_disable_regulators; } - goto retry; } else { @@ -1088,13 +1218,25 @@ static int lt9611c_probe(struct i2c_client *client) } lt9611c_unlock(lt9611c); + + /* Select port B so the chip is configured for the correct DSI input */ + msleep(200); + ret = lt9611c_select_port(lt9611c, PORT_SWAP_B); + if (ret < 0) { + dev_warn(dev, "port B selection failed (%d), HPD may not work\n", ret); + lt9611c->selected_port = -1; + } else { + lt9611c->selected_port = PORT_SWAP_B; + } + msleep(200); + dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); INIT_WORK(<9611c->work, lt9611c_hpd_work); ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, lt9611c_irq_thread_handler, - IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_NO_AUTOEN, "lt9611c", lt9611c); @@ -1111,6 +1253,20 @@ static int lt9611c_probe(struct i2c_client *client) DRM_BRIDGE_OP_HDMI_AUDIO; lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + lt9611c->bridge.vendor = "Lontium"; + switch (lt9611c->chip_type) { + case CHIP_LT9611C: + lt9611c->bridge.product = "LT9611C"; + break; + case CHIP_LT9611EX: + lt9611c->bridge.product = "LT9611EX"; + break; + case CHIP_LT9611UXD: + default: + lt9611c->bridge.product = "LT9611UXD"; + break; + } + lt9611c->bridge.hdmi_audio_dev = dev; lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; lt9611c->bridge.hdmi_audio_dai_port = 2; @@ -1135,19 +1291,33 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->hdmi_connected = false; i2c_set_clientdata(client, lt9611c); + + /* Enable HPD interrupt in the chip */ + { + unsigned int irq_status; + + mutex_lock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + regmap_read(lt9611c->regmap, 0xe084, &irq_status); + if (irq_status) { + regmap_write(lt9611c->regmap, 0xe0df, irq_status); + msleep(20); + regmap_write(lt9611c->regmap, 0xe0df, 0x00); + } + regmap_write(lt9611c->regmap, 0xe0d0, 0x01); + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + mutex_unlock(<9611c->ocm_lock); + } + enable_irq(client->irq); - lt9611c_reset(lt9611c); + msleep(100); return 0; err_remove_bridge: - free_irq(client->irq, lt9611c); cancel_work_sync(<9611c->work); - drm_bridge_remove(<9611c->bridge); err_disable_regulators: - regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - err_of_put: of_node_put(lt9611c->dsi1_node); of_node_put(lt9611c->dsi0_node); @@ -1159,9 +1329,11 @@ static void lt9611c_remove(struct i2c_client *client) { struct lt9611c *lt9611c = i2c_get_clientdata(client); - free_irq(client->irq, lt9611c); + /* + * IRQ was requested with devm_request_threaded_irq and is freed + * automatically by devres — do NOT call free_irq() here. + */ cancel_work_sync(<9611c->work); - regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); of_node_put(lt9611c->dsi1_node); of_node_put(lt9611c->dsi0_node); } @@ -1169,18 +1341,14 @@ static void lt9611c_remove(struct i2c_client *client) static int lt9611c_bridge_suspend(struct device *dev) { struct lt9611c *lt9611c = dev_get_drvdata(dev); - int ret; dev_dbg(lt9611c->dev, "suspend\n"); disable_irq(lt9611c->client->irq); - ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - if (ret) { - dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); - return ret; - } gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + if (lt9611c->hdmi_gpio) + gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 0); - return ret; + return 0; } static int lt9611c_bridge_resume(struct device *dev) @@ -1188,16 +1356,25 @@ static int lt9611c_bridge_resume(struct device *dev) struct lt9611c *lt9611c = dev_get_drvdata(dev); int ret; - ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); - if (ret) { - dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); - return ret; + if (lt9611c->hdmi_gpio) { + gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); + msleep(20); } - enable_irq(lt9611c->client->irq); lt9611c_reset(lt9611c); + + /* Reapply port selection after reset, same as atomic_pre_enable */ + if (lt9611c->selected_port >= 0) { + msleep(200); + ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); + if (ret < 0) + dev_warn(lt9611c->dev, "resume: failed to reapply port selection, ret=%d\n", ret); + msleep(200); + } + + enable_irq(lt9611c->client->irq); dev_dbg(lt9611c->dev, "resume\n"); - return ret; + return 0; } static const struct dev_pm_ops lt9611c_bridge_pm_ops = { @@ -1214,9 +1391,9 @@ static struct i2c_device_id lt9611c_id[] = { }; static const struct of_device_id lt9611c_match_table[] = { - { .compatible = "lontium,lt9611c" }, - { .compatible = "lontium,lt9611ex" }, - { .compatible = "lontium,lt9611uxd" }, + { .compatible = "lontium,lt9611c", .data = (void *)CHIP_LT9611C }, + { .compatible = "lontium,lt9611ex", .data = (void *)CHIP_LT9611EX }, + { .compatible = "lontium,lt9611uxd", .data = (void *)CHIP_LT9611UXD }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, lt9611c_match_table); @@ -1238,4 +1415,3 @@ MODULE_AUTHOR("SunYun Yang "); MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FW_FILE); - From 63edd2b8cdac833b11c4c587be75a154f4956705 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 28 May 2026 22:04:24 +0530 Subject: [PATCH 0971/1058] arm64: defconfig: Enable LT9611C bridge driver This driver provides access to LT9611C bridge driver to access Lontium LT9611UXD DSI to HDMI chip. Signed-off-by: Mohit Dsor --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7d4b24b378a5d..066b854b3f973 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -963,6 +963,7 @@ CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m CONFIG_DRM_LONTIUM_LT9611=m +CONFIG_DRM_LONTIUM_LT9611C=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m CONFIG_DRM_ITE_IT66121=m From e94db5a2635aa4ce214a28965afcc44749aae938 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 29 May 2026 19:42:31 +0530 Subject: [PATCH 0972/1058] soc: qcom: llcc: Add configuration data for Shikra SoC Add Last Level Cache table and configs for the Shikra SoC. Signed-off-by: Komal Bajaj --- drivers/soc/qcom/llcc-qcom.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8948b5fd42d2a..22c8099cf6bbb 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -2305,6 +2305,20 @@ static const struct llcc_slice_config sdm845_data[] = {{ }, }; +static const struct llcc_slice_config shikra_data[] = { + { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .activate_on_init = true, + .vict_prio = true, + }, +}; + static const struct llcc_slice_config sm6350_data[] = { { .usecase_id = LLCC_CPUSS, @@ -4575,6 +4589,15 @@ static const struct qcom_llcc_config sdm845_cfg[] = { }, }; +static const struct qcom_llcc_config shikra_cfg[] = { + { + .sct_data = shikra_data, + .size = ARRAY_SIZE(shikra_data), + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + }, +}; + static const struct qcom_llcc_config sm6350_cfg[] = { { .sct_data = sm6350_data, @@ -4752,6 +4775,11 @@ static const struct qcom_sct_config sdm845_cfgs = { .num_config = ARRAY_SIZE(sdm845_cfg), }; +static const struct qcom_sct_config shikra_cfgs = { + .llcc_config = shikra_cfg, + .num_config = ARRAY_SIZE(shikra_cfg), +}; + static const struct qcom_sct_config sm6350_cfgs = { .llcc_config = sm6350_cfg, .num_config = ARRAY_SIZE(sm6350_cfg), @@ -5632,6 +5660,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfgs }, { .compatible = "qcom,sdm670-llcc", .data = &sdm670_cfgs }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfgs }, + { .compatible = "qcom,shikra-llcc", .data = &shikra_cfgs }, { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfgs }, { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfgs }, { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfgs }, From 3391416762a3030f331acebb3cd4db8abd11d6ee Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 3 Jun 2026 17:52:25 +0530 Subject: [PATCH 0973/1058] dt-bindings: firmware: qcom,scm: complete shikra clock constraints Extend the incomplete shikra binding by adding qcom,scm-shikra to the allOf blocks that enforce clock requirements and constrain clock count. Signed-off-by: Komal Bajaj --- Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index aa2b2d4fe71b3..9d64765416137 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -149,6 +149,7 @@ allOf: - qcom,scm-msm8974 - qcom,scm-msm8976 - qcom,scm-qcm2290 + - qcom,scm-shikra - qcom,scm-sm6375 then: required: @@ -168,6 +169,7 @@ allOf: - qcom,scm-msm8660 - qcom,scm-msm8960 - qcom,scm-qcm2290 + - qcom,scm-shikra - qcom,scm-sm6375 then: properties: From 0f4e10a2afb30c22c6653f0f1e7ec15035a60b47 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:43 +0530 Subject: [PATCH 0974/1058] dt-bindings: phy: sc8280xp-qmp-pcie: Document Shikra PCIe phy Document the compatible of the Shikra PCIe phy which supports Gen2x1. Signed-off-by: Sushrut Shree Trivedi Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-1-e1a721eb8943@oss.qualcomm.com --- .../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 108cf9dc86ea0..b9b0fa26347bb 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -34,6 +34,7 @@ properties: - qcom,sdm845-qmp-pcie-phy - qcom,sdx55-qmp-pcie-phy - qcom,sdx65-qmp-gen4x2-pcie-phy + - qcom,shikra-qmp-gen2x1-pcie-phy - qcom,sm8150-qmp-gen3x1-pcie-phy - qcom,sm8150-qmp-gen3x2-pcie-phy - qcom,sm8250-qmp-gen3x1-pcie-phy @@ -166,6 +167,7 @@ allOf: - qcom,sdm845-qhp-pcie-phy - qcom,sdm845-qmp-pcie-phy - qcom,sdx55-qmp-pcie-phy + - qcom,shikra-qmp-gen2x1-pcie-phy - qcom,sm8150-qmp-gen3x1-pcie-phy - qcom,sm8150-qmp-gen3x2-pcie-phy - qcom,sm8250-qmp-gen3x1-pcie-phy From 053beeaabdb32e437eb12ae52c5467a2931d8400 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:44 +0530 Subject: [PATCH 0975/1058] dt-bindings: PCI: qcom: Document the Shikra PCIe Controller Add a dedicated schema for the PCIe controller found on the Shikra platform. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-2-e1a721eb8943@oss.qualcomm.com --- .../bindings/pci/qcom,shikra-pcie.yaml | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml diff --git a/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml new file mode 100644 index 0000000000000..f9d1dba9dd2e8 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/qcom,shikra-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Shikra PCI Express Root Complex + +maintainers: + - Bjorn Andersson + - Manivannan Sadhasivam + +description: + Qualcomm Shikra SoC (and compatible) PCIe root complex controller is based on + the Synopsys DesignWare PCIe IP. + +properties: + compatible: + const: qcom,shikra-pcie + + reg: + minItems: 5 + maxItems: 6 + + reg-names: + minItems: 5 + items: + - const: parf # Qualcomm specific registers + - const: dbi # DesignWare PCIe registers + - const: elbi # External local bus interface registers + - const: atu # ATU address space + - const: config # PCIe configuration space + - const: mhi # MHI registers + + clocks: + minItems: 7 + maxItems: 9 + + clock-names: + minItems: 7 + items: + - const: aux # Auxiliary clock + - const: cfg # Configuration clock + - const: bus_master # Master AXI clock + - const: bus_slave # Slave AXI clock + - const: slave_q2a # Slave Q2A clock + - const: ddrss_memnoc_pcie # PCIe SF MEMNOC clock + - const: tile # PCIe tile SYS NoC clock + - const: qmip_pcie_ahb # QMIP PCIe AHB clock + + interrupts: + minItems: 8 + maxItems: 9 + + interrupt-names: + minItems: 8 + items: + - const: msi0 + - const: msi1 + - const: msi2 + - const: msi3 + - const: msi4 + - const: msi5 + - const: msi6 + - const: msi7 + - const: global + + resets: + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + items: + - const: pci # PCIe core reset + - const: link_down # PCIe link down reset + +required: + - power-domains + - resets + - reset-names + +allOf: + - $ref: qcom,pcie-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,shikra-pcie"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>, + <0x03000000 0x4 0x00000000 0x4 0x00000000 0x3 0x0000000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ddrss_memnoc_pcie", + "tile", + "qmip_pcie_ahb"; + + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", + "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + max-link-speed = <2>; + + operating-points-v2 = <&pcie_opp_table>; + + status = "disabled"; + + pcie_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + }; + }; From 87d4ccb3cb505c96218aef978949e6e2261b9680 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:45 +0530 Subject: [PATCH 0976/1058] dt-bindings: PCI: Add bindings for endpoint gpios Add devicetree bindings for TC9563 GPIO's which are used to control endpoint power and reset. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-3-e1a721eb8943@oss.qualcomm.com --- .../bindings/pci/toshiba,tc9563.yaml | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml index b3ad05d90201c..f9f71f28aa92b 100644 --- a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml +++ b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml @@ -26,6 +26,11 @@ properties: reg: maxItems: 1 + gpio-controller: true + + '#gpio-cells': + const: 2 + resx-gpios: maxItems: 1 description: @@ -69,6 +74,17 @@ $defs: type: object properties: + reset-gpios: + description: + Specify the TC9563 GPIO used to reset the endpoint + connected to the particular TC9563 downstream port. + + ep-pwr-en-gpios: + description: + Specify the TC9563 GPIO used for enabling power to + the endpoint connected to the particular TC9563 + downstream port. + toshiba,tx-amplitude-microvolt: description: Change Tx Margin setting for low power consumption. @@ -104,7 +120,7 @@ examples: #address-cells = <3>; #size-cells = <2>; - pcie@0 { + tc9563: pcie@0 { device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; @@ -120,6 +136,7 @@ examples: device_type = "pci"; #address-cells = <3>; #size-cells = <2>; + #gpio-cells = <2>; ranges; bus-range = <0x02 0xff>; @@ -154,6 +171,9 @@ examples: device_type = "pci"; ranges; bus-range = <0x04 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tc9563 5 GPIO_ACTIVE_LOW>; }; pcie@3,0 { From e309c1f66c6e9b695a601b665a693bb504967907 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:46 +0530 Subject: [PATCH 0977/1058] PCI: qcom: Add support for Shikra Add support for the single PCIe controller on Shikra platform which is capable of Gen2x1 operation. Signed-off-by: Sushrut Shree Trivedi Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-4-e1a721eb8943@oss.qualcomm.com --- drivers/pci/controller/dwc/pcie-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index d8eb52857f69c..19daadee65f7c 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -2309,6 +2309,7 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-x1e80100", .data = &cfg_sc8280xp }, + { .compatible = "qcom,shikra-pcie", .data = &cfg_1_9_0 }, { } }; From abc5eb341f9f2914b75756dfb64a64999f355c9b Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:47 +0530 Subject: [PATCH 0978/1058] phy: qcom: qmp-pcie: Add QMP PCIe PHY support for Shikra Add QMP PCIe PHY Gen2x1 support. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-5-e1a721eb8943@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 73 ++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index d3effad7a074b..e0995e4d5f2dc 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -2172,6 +2172,50 @@ static const struct qmp_phy_init_tbl sdx65_qmp_pcie_pcs_lane1_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), }; +static const struct qmp_phy_init_tbl shikra_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x9), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x3), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0xd), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x35), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_EP_DIV, 0x19), +}; + static const struct qmp_phy_init_tbl sm8450_qmp_gen3_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), @@ -3911,6 +3955,32 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { .phy_status = PHYSTATUS, }; +static const struct qmp_phy_cfg shikra_pciephy_cfg = { + .lanes = 1, + + .offsets = &qmp_pcie_offsets_v2, + + .tbls = { + .serdes = shikra_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(shikra_pcie_serdes_tbl), + .tx = qcs615_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(qcs615_pcie_tx_tbl), + .rx = qcs615_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(qcs615_pcie_rx_tbl), + .pcs = qcs615_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(qcs615_pcie_pcs_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v2_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + + static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { .lanes = 1, @@ -5603,6 +5673,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { }, { .compatible = "qcom,sdx65-qmp-gen4x2-pcie-phy", .data = &sdx65_qmp_pciephy_cfg, + }, { + .compatible = "qcom,shikra-qmp-gen2x1-pcie-phy", + .data = &shikra_pciephy_cfg, }, { .compatible = "qcom,sm8150-qmp-gen3x1-pcie-phy", .data = &sm8250_qmp_gen3x1_pciephy_cfg, From b77d8ec712e7eb292c933fa8b8470cad2aa02587 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:48 +0530 Subject: [PATCH 0979/1058] PCI/pwrctrl: tc9563: Add API to control endpoint power and reset Some platform utilise TC9563 GPIOs to enable power and control reset of endpoints. This patch adds support to parse endpoint reset and power enable gpios from each TC9563 port node in the devicetree. To configure these GPIO's during the POWER ON sequence, two new API's are introduced: tc9563_ep_pwr_en() and tc9563_ep_assert_deassert_reset(). Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-6-e1a721eb8943@oss.qualcomm.com --- drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c | 152 +++++++++++++++++++---- 1 file changed, 129 insertions(+), 23 deletions(-) diff --git a/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c index 488e1ec34a7fb..b9912f0225550 100644 --- a/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c +++ b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c @@ -63,6 +63,8 @@ #define TC9563_TX_MARGIN_MIN_UA 400000 +#define TC9563_GPIO_NONE (-1) + /* * From TC9563 PORSYS rev 0.2, figure 1.1 POR boot sequence * wait for 10ms for the internal osc frequency to stabilize. @@ -92,6 +94,10 @@ struct tc9563_pwrctrl_cfg { u8 nfts[2]; /* GEN1 & GEN2 */ bool disable_dfe; bool disable_port; + + int ep_reset_gpio; + int ep_pwr_en_gpio; + }; #define TC9563_PWRCTL_MAX_SUPPLY 6 @@ -257,6 +263,89 @@ static int tc9563_pwrctrl_disable_port(struct tc9563_pwrctrl *tc9563, ARRAY_SIZE(common_pwroff_seq)); } +static int tc9563_pwrctrl_ep_pwr_en(struct tc9563_pwrctrl *tc9563, + enum tc9563_pwrctrl_ports port, + bool enable, int ep_pwr_en_gpio) +{ + u32 ep_pwr_en_gpio_mask, val; + int ret; + + if (ep_pwr_en_gpio == TC9563_GPIO_NONE) + return 0; + + ep_pwr_en_gpio_mask = BIT(ep_pwr_en_gpio); + + /* Set TC9563 GPIO as output */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_GPIO_CONFIG, + &val); + if (ret) + return ret; + + val &= ~ep_pwr_en_gpio_mask; + + ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, + val); + if (ret) + return ret; + + /* Toggle 0->1 to enable power */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_RESET_GPIO, + &val); + if (ret) + return ret; + + val = enable ? (val | ep_pwr_en_gpio_mask) : (val & ~ep_pwr_en_gpio_mask); + + return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); + +} + +static int tc9563_pwrctrl_ep_assert_deassert_reset(struct tc9563_pwrctrl *tc9563, + enum tc9563_pwrctrl_ports port, + bool deassert, int ep_reset_gpio) +{ + u32 ep_reset_gpio_mask, val; + int ret; + + if (ep_reset_gpio == TC9563_GPIO_NONE) { + switch (port) { + case TC9563_DSP1: + ep_reset_gpio = 0x2; + break; + case TC9563_DSP2: + ep_reset_gpio = 0x3; + break; + default: + return 0; + } + } + + ep_reset_gpio_mask = BIT(ep_reset_gpio); + + /* Set TC9563 GPIO as output */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_GPIO_CONFIG, + &val); + if (ret) + return ret; + + val &= ~ep_reset_gpio_mask; + + ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, + val); + if (ret) + return ret; + + /* Assert-deassert endpoint reset */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_RESET_GPIO, + &val); + if (ret) + return ret; + + val = deassert ? (val | ep_reset_gpio_mask) : (val & ~ep_reset_gpio_mask); + + return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); +} + static int tc9563_pwrctrl_set_l0s_l1_entry_delay(struct tc9563_pwrctrl *tc9563, enum tc9563_pwrctrl_ports port, bool is_l1, u32 ns) @@ -401,28 +490,17 @@ static int tc9563_pwrctrl_set_nfts(struct tc9563_pwrctrl *tc9563, ARRAY_SIZE(nfts_seq)); } -static int tc9563_pwrctrl_assert_deassert_reset(struct tc9563_pwrctrl *tc9563, - bool deassert) -{ - int ret, val; - - ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, - TC9563_GPIO_MASK); - if (ret) - return ret; - - val = deassert ? TC9563_GPIO_DEASSERT_BITS : 0; - - return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); -} - static int tc9563_pwrctrl_parse_device_dt(struct tc9563_pwrctrl *tc9563, struct device_node *node, enum tc9563_pwrctrl_ports port) { struct tc9563_pwrctrl_cfg *cfg = &tc9563->cfg[port]; + struct of_phandle_args args; int ret; + cfg->ep_reset_gpio = TC9563_GPIO_NONE; + cfg->ep_pwr_en_gpio = TC9563_GPIO_NONE; + /* Disable port if the status of the port is disabled. */ if (!of_device_is_available(node)) { cfg->disable_port = true; @@ -437,6 +515,18 @@ static int tc9563_pwrctrl_parse_device_dt(struct tc9563_pwrctrl *tc9563, if (ret && ret != -EINVAL) return ret; + ret = of_parse_phandle_with_fixed_args(node, "ep-pwr-en-gpios", 2, 0, &args); + if (ret && ret != -ENOENT) + return ret; + else if (!ret) + cfg->ep_pwr_en_gpio = args.args[0]; + + ret = of_parse_phandle_with_fixed_args(node, "reset-gpios", 2, 0, &args); + if (ret && ret != -ENOENT) + return ret; + else if (!ret) + cfg->ep_reset_gpio = args.args[0]; + ret = of_property_read_u32(node, "toshiba,tx-amplitude-microvolt", &cfg->tx_amp); if (ret && ret != -EINVAL) return ret; @@ -479,18 +569,28 @@ static int tc9563_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) fsleep(TC9563_OSC_STAB_DELAY_US); - ret = tc9563_pwrctrl_assert_deassert_reset(tc9563, false); - if (ret) - goto power_off; - for (i = 0; i < TC9563_MAX; i++) { cfg = &tc9563->cfg[i]; + ret = tc9563_pwrctrl_disable_port(tc9563, i); if (ret) { dev_err(dev, "Disabling port failed\n"); goto power_off; } + ret = tc9563_pwrctrl_ep_assert_deassert_reset(tc9563, i, false, + cfg->ep_reset_gpio); + if (ret) { + dev_err(dev, "Assert EP reset failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_ep_pwr_en(tc9563, i, true, cfg->ep_pwr_en_gpio); + if (ret) { + dev_err(dev, "Enabling EP Power failed\n"); + goto power_off; + } + ret = tc9563_pwrctrl_set_l0s_l1_entry_delay(tc9563, i, false, cfg->l0s_delay); if (ret) { dev_err(dev, "Setting L0s entry delay failed\n"); @@ -520,11 +620,17 @@ static int tc9563_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) dev_err(dev, "Disabling DFE failed\n"); goto power_off; } + + ret = tc9563_pwrctrl_ep_assert_deassert_reset(tc9563, i, true, + cfg->ep_reset_gpio); + if (ret) { + dev_err(dev, "De-assert EP reset failed\n"); + goto power_off; + } + } - ret = tc9563_pwrctrl_assert_deassert_reset(tc9563, true); - if (!ret) - return 0; + return 0; power_off: tc9563_pwrctrl_power_off(&tc9563->pwrctrl); @@ -602,7 +708,7 @@ static int tc9563_pwrctrl_probe(struct platform_device *pdev) port++; ret = tc9563_pwrctrl_parse_device_dt(tc9563, child1, port); - if (ret) + if (port + 1 >= TC9563_MAX || ret) break; } } From bb2b20c6072849f476353984aeaa0389ad522208 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 25 May 2026 17:46:39 +0530 Subject: [PATCH 0980/1058] clk: qcom: Revert the DISPCC/GPUCC bindings and driver changes Revert the DISPCC/GPUCC bindings and driver changes to re-use Agatti. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,shikra-dispcc.yaml | 62 -- .../bindings/clock/qcom,sm6115-gpucc.yaml | 6 +- drivers/clk/qcom/Kconfig | 19 - drivers/clk/qcom/Makefile | 2 - drivers/clk/qcom/dispcc-shikra.c | 565 ------------------ drivers/clk/qcom/gpucc-shikra.c | 407 ------------- .../dt-bindings/clock/qcom,shikra-dispcc.h | 39 -- include/dt-bindings/clock/qcom,shikra-gpucc.h | 37 -- 8 files changed, 1 insertion(+), 1136 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml delete mode 100644 drivers/clk/qcom/dispcc-shikra.c delete mode 100644 drivers/clk/qcom/gpucc-shikra.c delete mode 100644 include/dt-bindings/clock/qcom,shikra-dispcc.h delete mode 100644 include/dt-bindings/clock/qcom,shikra-gpucc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml deleted file mode 100644 index dbaecdd3e0b4b..0000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,shikra-dispcc.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/clock/qcom,shikra-dispcc.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Display Clock & Reset Controller for Qualcomm Shikra SoC - -maintainers: - - Imran Shaik - -description: | - Display clock control module provides the clocks, resets and power - domains on Qualcomm Shikra SoC platform. - - See also: - - include/dt-bindings/clock/qcom,shikra-dispcc.h - -properties: - compatible: - enum: - - qcom,shikra-dispcc - - clocks: - items: - - description: Board XO source - - description: Board sleep clock - - description: GPLL0 DISP DIV clock from GCC - - description: Byte clock from DSI PHY0 - - description: Pixel clock from DSI PHY0 - - description: Byte clock from DSI PHY1 - - description: Pixel clock from DSI PHY1 - -required: - - compatible - - clocks - - '#power-domain-cells' - -allOf: - - $ref: qcom,gcc.yaml# - -unevaluatedProperties: false - -examples: - - | - #include - #include - clock-controller@5f00000 { - compatible = "qcom,shikra-dispcc"; - reg = <0x5f00000 0x20000>; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, - <&sleep_clk>, - <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, - <&dsi0_phy 0>, - <&dsi0_phy 1>, - <&dsi1_phy 0>, - <&dsi1_phy 1>; - #clock-cells = <1>; - #power-domain-cells = <1>; - #reset-cells = <1>; - }; -... diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml index 1f6b5cec4642a..21998c6bf5575 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml @@ -8,20 +8,16 @@ title: Qualcomm Graphics Clock & Reset Controller on SM6115 maintainers: - Konrad Dybcio - - Imran Shaik description: | Qualcomm graphics clock control module provides clocks, resets and power domains on Qualcomm SoCs. - See also: - include/dt-bindings/clock/qcom,shikra-gpucc.h - include/dt-bindings/clock/qcom,sm6115-gpucc.h + See also: include/dt-bindings/clock/qcom,shikra-gpucc.h properties: compatible: enum: - - qcom,shikra-gpucc - qcom,sm6115-gpucc clocks: diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index dfc96dc163b50..f5b08406d0178 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -166,16 +166,6 @@ config CLK_SHIKRA_AUDIOCORECC Say Y if you want to use AudioCoreCC clocks required to support audio devices and it's functionality. -config CLK_SHIKRA_DISPCC - tristate "Shikra Display Clock Controller" - depends on ARM64 || COMPILE_TEST - select CLK_SHIKRA_GCC - help - Support for the display clock controller on Qualcomm Technologies, Inc - Shikra devices. - Say Y if you want to support display devices and functionality such as - splash screen. - config CLK_SHIKRA_GCC tristate "Shikra Global Clock Controller" depends on ARM64 || COMPILE_TEST @@ -185,15 +175,6 @@ config CLK_SHIKRA_GCC Say Y if you want to use multimedia devices or peripheral devices such as Camera, Video, UART, SPI, I2C, USB, SD/eMMC etc. -config CLK_SHIKRA_GPUCC - tristate "Shikra Graphics Clock Controller" - depends on ARM64 || COMPILE_TEST - select CLK_SHIKRA_GCC - help - Support for the graphics clock controller on Shikra devices. - Say Y if you want to support graphics controller devices and - functionality such as 3D graphics. - config CLK_X1E80100_CAMCC tristate "X1E80100 Camera Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 38b77a2a2712a..90fc993667d20 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -40,9 +40,7 @@ obj-$(CONFIG_CLK_KAANAPALI_VIDEOCC) += videocc-kaanapali.o obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o obj-$(CONFIG_CLK_SHIKRA_AUDIOCORECC) += audiocorecc-shikra.o -obj-$(CONFIG_CLK_SHIKRA_DISPCC) += dispcc-shikra.o obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o -obj-$(CONFIG_CLK_SHIKRA_GPUCC) += gpucc-shikra.o obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_GCC) += gcc-x1e80100.o diff --git a/drivers/clk/qcom/dispcc-shikra.c b/drivers/clk/qcom/dispcc-shikra.c deleted file mode 100644 index f4ae20f190465..0000000000000 --- a/drivers/clk/qcom/dispcc-shikra.c +++ /dev/null @@ -1,565 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -#include -#include -#include -#include -#include - -#include - -#include "clk-alpha-pll.h" -#include "clk-branch.h" -#include "clk-pll.h" -#include "clk-rcg.h" -#include "clk-regmap.h" -#include "clk-regmap-divider.h" -#include "clk-regmap-mux.h" -#include "common.h" -#include "gdsc.h" -#include "reset.h" - -enum { - DT_BI_TCXO, - DT_SLEEP_CLK, - DT_GPLL0, - DT_DSI0_PHY_PLL_OUT_BYTECLK, - DT_DSI0_PHY_PLL_OUT_DSICLK, - DT_DSI1_PHY_PLL_OUT_BYTECLK, - DT_DSI1_PHY_PLL_OUT_DSICLK, -}; - -enum { - P_BI_TCXO, - P_DISP_CC_PLL0_OUT_MAIN, - P_DSI0_PHY_PLL_OUT_BYTECLK, - P_DSI0_PHY_PLL_OUT_DSICLK, - P_DSI1_PHY_PLL_OUT_DSICLK, - P_GPLL0_OUT_MAIN, - P_SLEEP_CLK, -}; - -static const struct pll_vco spark_vco[] = { - { 500000000, 1000000000, 2 }, -}; - -/* 768.0 MHz Configuration */ -static const struct alpha_pll_config disp_cc_pll0_config = { - .l = 0x28, - .alpha = 0x0, - .alpha_en_mask = BIT(24), - .vco_val = BIT(21), - .vco_mask = GENMASK(21, 20), - .main_output_mask = BIT(0), - .config_ctl_val = 0x4001055b, - .test_ctl_hi1_val = 0x1, -}; - -static struct clk_alpha_pll disp_cc_pll0 = { - .offset = 0x0, - .config = &disp_cc_pll0_config, - .vco_table = spark_vco, - .num_vco = ARRAY_SIZE(spark_vco), - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], - .clkr = { - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_pll0", - .parent_data = &(const struct clk_parent_data) { - .index = DT_BI_TCXO, - }, - .num_parents = 1, - .ops = &clk_alpha_pll_ops, - }, - }, -}; - -static const struct parent_map disp_cc_parent_map_0[] = { - { P_BI_TCXO, 0 }, - { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_0[] = { - { .index = DT_BI_TCXO }, - { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, -}; - -static const struct parent_map disp_cc_parent_map_1[] = { - { P_BI_TCXO, 0 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_1[] = { - { .index = DT_BI_TCXO }, -}; - -static const struct parent_map disp_cc_parent_map_2[] = { - { P_BI_TCXO, 0 }, - { P_GPLL0_OUT_MAIN, 4 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_2[] = { - { .index = DT_BI_TCXO }, - { .index = DT_GPLL0 }, -}; - -static const struct parent_map disp_cc_parent_map_3[] = { - { P_BI_TCXO, 0 }, - { P_DISP_CC_PLL0_OUT_MAIN, 1 }, - { P_GPLL0_OUT_MAIN, 4 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_3[] = { - { .index = DT_BI_TCXO }, - { .hw = &disp_cc_pll0.clkr.hw }, - { .index = DT_GPLL0 }, -}; - -static const struct parent_map disp_cc_parent_map_4[] = { - { P_BI_TCXO, 0 }, - { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, - { P_DSI1_PHY_PLL_OUT_DSICLK, 2 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_4[] = { - { .index = DT_BI_TCXO }, - { .index = DT_DSI0_PHY_PLL_OUT_DSICLK }, - { .index = DT_DSI1_PHY_PLL_OUT_DSICLK }, -}; - -static const struct parent_map disp_cc_parent_map_5[] = { - { P_SLEEP_CLK, 0 }, -}; - -static const struct clk_parent_data disp_cc_parent_data_5[] = { - { .index = DT_SLEEP_CLK }, -}; - -static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0), - F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0), - { } -}; - -static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = { - .cmd_rcgr = 0x2154, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_2, - .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_ahb_clk_src", - .parent_data = disp_cc_parent_data_2, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { - .cmd_rcgr = 0x20a4, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_0, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_byte0_clk_src", - .parent_data = disp_cc_parent_data_0, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .flags = CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT, - .ops = &clk_byte2_ops, - }, -}; - -static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - { } -}; - -static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { - .cmd_rcgr = 0x20c0, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_0, - .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_esc0_clk_src", - .parent_data = disp_cc_parent_data_0, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0), - F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), - F(307200000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0), - F(384000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0), - { } -}; - -static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = { - .cmd_rcgr = 0x2074, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_mdp_clk_src", - .parent_data = disp_cc_parent_data_3, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { - .cmd_rcgr = 0x205c, - .mnd_width = 8, - .hid_width = 5, - .parent_map = disp_cc_parent_map_4, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_pclk0_clk_src", - .parent_data = disp_cc_parent_data_4, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), - .flags = CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT, - .ops = &clk_pixel_ops, - }, -}; - -static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = { - .cmd_rcgr = 0x208c, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_1, - .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_vsync_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = { - F(32764, P_SLEEP_CLK, 1, 0, 0), - { } -}; - -static struct clk_rcg2 disp_cc_sleep_clk_src = { - .cmd_rcgr = 0x6050, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_5, - .freq_tbl = ftbl_disp_cc_sleep_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_sleep_clk_src", - .parent_data = disp_cc_parent_data_5, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), - .ops = &clk_rcg2_ops, - }, -}; - -static struct clk_rcg2 disp_cc_xo_clk_src = { - .cmd_rcgr = 0x6034, - .mnd_width = 0, - .hid_width = 5, - .parent_map = disp_cc_parent_map_1, - .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_xo_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), - .ops = &clk_rcg2_shared_ops, - }, -}; - -static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { - .reg = 0x20bc, - .shift = 0, - .width = 2, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_byte0_div_clk_src", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_byte0_clk_src.clkr.hw, - }, - .num_parents = 1, - .ops = &clk_regmap_div_ops, - }, -}; - -static struct clk_branch disp_cc_mdss_ahb_clk = { - .halt_reg = 0x2044, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2044, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_ahb_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_ahb_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_byte0_clk = { - .halt_reg = 0x201c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x201c, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_byte0_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_byte0_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_byte0_intf_clk = { - .halt_reg = 0x2020, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2020, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_byte0_intf_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_byte0_div_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_esc0_clk = { - .halt_reg = 0x2024, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2024, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_esc0_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_esc0_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_mdp_clk = { - .halt_reg = 0x2008, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2008, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_mdp_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_mdp_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_mdp_lut_clk = { - .halt_reg = 0x2010, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x2010, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_mdp_lut_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_mdp_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = { - .halt_reg = 0x4004, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x4004, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_non_gdsc_ahb_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_ahb_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_pclk0_clk = { - .halt_reg = 0x2004, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2004, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_pclk0_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_pclk0_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch disp_cc_mdss_vsync_clk = { - .halt_reg = 0x2018, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x2018, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "disp_cc_mdss_vsync_clk", - .parent_hws = (const struct clk_hw*[]) { - &disp_cc_mdss_vsync_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct gdsc disp_cc_mdss_core_gdsc = { - .gdscr = 0x3000, - .en_rest_wait_val = 0x2, - .en_few_wait_val = 0x2, - .clk_dis_wait_val = 0xf, - .pd = { - .name = "disp_cc_mdss_core_gdsc", - }, - .pwrsts = PWRSTS_OFF_ON, - .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, -}; - -static struct clk_regmap *disp_cc_shikra_clocks[] = { - [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr, - [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr, - [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr, - [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr, - [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr, - [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr, - [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, - [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, - [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr, - [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr, - [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr, - [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr, - [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr, - [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr, - [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr, - [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr, - [DISP_CC_PLL0] = &disp_cc_pll0.clkr, - [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, - [DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr, -}; - -static struct gdsc *disp_cc_shikra_gdscs[] = { - [DISP_CC_MDSS_CORE_GDSC] = &disp_cc_mdss_core_gdsc, -}; - -static const struct qcom_reset_map disp_cc_shikra_resets[] = { - [DISP_CC_MDSS_CORE_BCR] = { 0x2000 }, - [DISP_CC_MDSS_RSCC_BCR] = { 0x4000 }, -}; - -static struct clk_alpha_pll *disp_cc_shikra_plls[] = { - &disp_cc_pll0, -}; - -static u32 disp_cc_shikra_critical_cbcrs[] = { - 0x6068, /* DISP_CC_SLEEP_CLK */ - 0x604c, /* DISP_CC_XO_CLK */ -}; - -static const struct regmap_config disp_cc_shikra_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x10000, - .fast_io = true, -}; - -static struct qcom_cc_driver_data disp_cc_shikra_driver_data = { - .alpha_plls = disp_cc_shikra_plls, - .num_alpha_plls = ARRAY_SIZE(disp_cc_shikra_plls), - .clk_cbcrs = disp_cc_shikra_critical_cbcrs, - .num_clk_cbcrs = ARRAY_SIZE(disp_cc_shikra_critical_cbcrs), -}; - -static const struct qcom_cc_desc disp_cc_shikra_desc = { - .config = &disp_cc_shikra_regmap_config, - .clks = disp_cc_shikra_clocks, - .num_clks = ARRAY_SIZE(disp_cc_shikra_clocks), - .resets = disp_cc_shikra_resets, - .num_resets = ARRAY_SIZE(disp_cc_shikra_resets), - .gdscs = disp_cc_shikra_gdscs, - .num_gdscs = ARRAY_SIZE(disp_cc_shikra_gdscs), - .driver_data = &disp_cc_shikra_driver_data, -}; - -static const struct of_device_id disp_cc_shikra_match_table[] = { - { .compatible = "qcom,shikra-dispcc" }, - { } -}; -MODULE_DEVICE_TABLE(of, disp_cc_shikra_match_table); - -static int disp_cc_shikra_probe(struct platform_device *pdev) -{ - return qcom_cc_probe(pdev, &disp_cc_shikra_desc); -} - -static struct platform_driver disp_cc_shikra_driver = { - .probe = disp_cc_shikra_probe, - .driver = { - .name = "dispcc-shikra", - .of_match_table = disp_cc_shikra_match_table, - }, -}; - -module_platform_driver(disp_cc_shikra_driver); - -MODULE_DESCRIPTION("QTI DISPCC Shikra Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gpucc-shikra.c b/drivers/clk/qcom/gpucc-shikra.c deleted file mode 100644 index 4ad4fc0b6703a..0000000000000 --- a/drivers/clk/qcom/gpucc-shikra.c +++ /dev/null @@ -1,407 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -#include -#include -#include -#include -#include - -#include - -#include "clk-alpha-pll.h" -#include "clk-branch.h" -#include "clk-pll.h" -#include "clk-rcg.h" -#include "clk-regmap.h" -#include "clk-regmap-divider.h" -#include "clk-regmap-mux.h" -#include "common.h" -#include "gdsc.h" -#include "reset.h" - -enum { - DT_BI_TCXO, - DT_GPLL0_OUT_MAIN, - DT_GPLL0_OUT_MAIN_DIV, -}; - -enum { - P_BI_TCXO, - P_GPLL0_OUT_MAIN, - P_GPLL0_OUT_MAIN_DIV, - P_GPU_CC_PLL0_2X_DIV_CLK_SRC, - P_GPU_CC_PLL0_OUT_AUX, - P_GPU_CC_PLL0_OUT_AUX2, - P_GPU_CC_PLL0_OUT_MAIN, -}; - -static const struct pll_vco huayra_vco[] = { - { 600000000, 3300000000, 0 }, - { 600000000, 2200000000, 1 }, -}; - -/* 710.4 MHz Configuration */ -static const struct alpha_pll_config gpu_cc_pll0_config = { - .l = 0x25, - .cal_l = 0x4e, - .alpha = 0x0, - .config_ctl_val = 0x200d4828, - .config_ctl_hi_val = 0x6, - .config_ctl_hi1_val = 0x00000000, - .test_ctl_val = 0x1c000000, - .test_ctl_hi_val = 0x00004000, - .test_ctl_hi1_val = 0x00000000, - .user_ctl_val = 0xf, -}; - -static struct clk_alpha_pll gpu_cc_pll0 = { - .offset = 0x0, - .config = &gpu_cc_pll0_config, - .vco_table = huayra_vco, - .num_vco = ARRAY_SIZE(huayra_vco), - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], - .clkr = { - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_pll0", - .parent_data = &(const struct clk_parent_data) { - .index = DT_BI_TCXO, - }, - .num_parents = 1, - .ops = &clk_alpha_pll_huayra_ops, - }, - }, -}; - -static const struct parent_map gpu_cc_parent_map_0[] = { - { P_BI_TCXO, 0 }, - { P_GPU_CC_PLL0_OUT_MAIN, 1 }, - { P_GPLL0_OUT_MAIN, 5 }, - { P_GPLL0_OUT_MAIN_DIV, 6 }, -}; - -static const struct clk_parent_data gpu_cc_parent_data_0[] = { - { .index = DT_BI_TCXO }, - { .hw = &gpu_cc_pll0.clkr.hw }, - { .index = DT_GPLL0_OUT_MAIN }, - { .index = DT_GPLL0_OUT_MAIN_DIV }, -}; - -static const struct parent_map gpu_cc_parent_map_1[] = { - { P_BI_TCXO, 0 }, - { P_GPU_CC_PLL0_2X_DIV_CLK_SRC, 1 }, - { P_GPU_CC_PLL0_OUT_AUX2, 2 }, - { P_GPU_CC_PLL0_OUT_AUX, 3 }, - { P_GPLL0_OUT_MAIN, 5 }, -}; - -static const struct clk_parent_data gpu_cc_parent_data_1[] = { - { .index = DT_BI_TCXO }, - { .hw = &gpu_cc_pll0.clkr.hw }, - { .hw = &gpu_cc_pll0.clkr.hw }, - { .hw = &gpu_cc_pll0.clkr.hw }, - { .index = DT_GPLL0_OUT_MAIN }, -}; - -static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { - F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), - { } -}; - -static struct clk_rcg2 gpu_cc_gmu_clk_src = { - .cmd_rcgr = 0x1120, - .mnd_width = 0, - .hid_width = 5, - .parent_map = gpu_cc_parent_map_0, - .freq_tbl = ftbl_gpu_cc_gmu_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_gmu_clk_src", - .parent_data = gpu_cc_parent_data_0, - .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { - F(355200000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), - F(537600000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), - F(672000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), - F(844800000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), - F(921600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), - F(1017600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), - F(1142400000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), - { } -}; - -static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { - .cmd_rcgr = 0x101c, - .mnd_width = 0, - .hid_width = 5, - .parent_map = gpu_cc_parent_map_1, - .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, - .hw_clk_ctrl = true, - .clkr.hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_gx_gfx3d_clk_src", - .parent_data = gpu_cc_parent_data_1, - .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_shared_ops, - }, -}; - -static struct clk_branch gpu_cc_crc_ahb_clk = { - .halt_reg = 0x107c, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x107c, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_crc_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_cx_gfx3d_clk = { - .halt_reg = 0x10a4, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x10a4, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_cx_gfx3d_clk", - .parent_hws = (const struct clk_hw*[]) { - &gpu_cc_gx_gfx3d_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = { - .halt_reg = 0x10a8, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x10a8, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_cx_gfx3d_slv_clk", - .parent_hws = (const struct clk_hw*[]) { - &gpu_cc_gx_gfx3d_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_cx_gmu_clk = { - .halt_reg = 0x1098, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x1098, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_cx_gmu_clk", - .parent_hws = (const struct clk_hw*[]) { - &gpu_cc_gmu_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { - .halt_reg = 0x108c, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x108c, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_cx_snoc_dvm_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_cxo_clk = { - .halt_reg = 0x109c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x109c, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_cxo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_gpu_smmu_vote_clk = { - .halt_reg = 0x5000, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x5000, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_gpu_smmu_vote_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_gx_gfx3d_clk = { - .halt_reg = 0x1054, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x1054, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_gx_gfx3d_clk", - .parent_hws = (const struct clk_hw*[]) { - &gpu_cc_gx_gfx3d_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gpu_cc_sleep_clk = { - .halt_reg = 0x1090, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x1090, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gpu_cc_sleep_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct gdsc gpu_cc_cx_gdsc = { - .gdscr = 0x106c, - .gds_hw_ctrl = 0x1540, - .en_rest_wait_val = 0x2, - .en_few_wait_val = 0x2, - .clk_dis_wait_val = 0x2, - .pd = { - .name = "gpu_cc_cx_gdsc", - }, - .pwrsts = PWRSTS_OFF_ON, - .flags = RETAIN_FF_ENABLE | VOTABLE, -}; - -static struct gdsc gpu_cc_gx_gdsc = { - .gdscr = 0x100c, - .clamp_io_ctrl = 0x1508, - .resets = (unsigned int []){ GPU_CC_GX_BCR }, - .reset_count = 1, - .en_rest_wait_val = 0x2, - .en_few_wait_val = 0x2, - .clk_dis_wait_val = 0x2, - .pd = { - .name = "gpu_cc_gx_gdsc", - }, - .pwrsts = PWRSTS_OFF_ON, - .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | SW_RESET | CLAMP_IO | AON_RESET, -}; - -static struct clk_regmap *gpu_cc_shikra_clocks[] = { - [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, - [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, - [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr, - [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, - [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, - [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, - [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, - [GPU_CC_GPU_SMMU_VOTE_CLK] = &gpu_cc_gpu_smmu_vote_clk.clkr, - [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, - [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, - [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, - [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, -}; - -static struct gdsc *gpu_cc_shikra_gdscs[] = { - [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, - [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc, -}; - -static const struct qcom_reset_map gpu_cc_shikra_resets[] = { - [GPU_CC_CX_BCR] = { 0x1068 }, - [GPU_CC_GFX3D_AON_BCR] = { 0x10a0 }, - [GPU_CC_GMU_BCR] = { 0x111c }, - [GPU_CC_GX_BCR] = { 0x1008 }, - [GPU_CC_XO_BCR] = { 0x1000 }, -}; - -static struct clk_alpha_pll *gpu_cc_shikra_plls[] = { - &gpu_cc_pll0, -}; - -static u32 gpu_cc_shikra_critical_cbcrs[] = { - 0x1078, /* GPU_CC_AHB_CLK */ - 0x1004, /* GPU_CC_CXO_AON_CLK */ - 0x1060, /* GPU_CC_GX_CXO_CLK */ -}; - -static const struct regmap_config gpu_cc_shikra_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7008, - .fast_io = true, -}; - -static struct qcom_cc_driver_data gpu_cc_shikra_driver_data = { - .alpha_plls = gpu_cc_shikra_plls, - .num_alpha_plls = ARRAY_SIZE(gpu_cc_shikra_plls), - .clk_cbcrs = gpu_cc_shikra_critical_cbcrs, - .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_shikra_critical_cbcrs), -}; - -static const struct qcom_cc_desc gpu_cc_shikra_desc = { - .config = &gpu_cc_shikra_regmap_config, - .clks = gpu_cc_shikra_clocks, - .num_clks = ARRAY_SIZE(gpu_cc_shikra_clocks), - .resets = gpu_cc_shikra_resets, - .num_resets = ARRAY_SIZE(gpu_cc_shikra_resets), - .gdscs = gpu_cc_shikra_gdscs, - .num_gdscs = ARRAY_SIZE(gpu_cc_shikra_gdscs), - .driver_data = &gpu_cc_shikra_driver_data, -}; - -static const struct of_device_id gpu_cc_shikra_match_table[] = { - { .compatible = "qcom,shikra-gpucc" }, - { } -}; -MODULE_DEVICE_TABLE(of, gpu_cc_shikra_match_table); - -static int gpu_cc_shikra_probe(struct platform_device *pdev) -{ - return qcom_cc_probe(pdev, &gpu_cc_shikra_desc); -} - -static struct platform_driver gpu_cc_shikra_driver = { - .probe = gpu_cc_shikra_probe, - .driver = { - .name = "gpucc-shikra", - .of_match_table = gpu_cc_shikra_match_table, - }, -}; - -module_platform_driver(gpu_cc_shikra_driver); - -MODULE_DESCRIPTION("QTI GPUCC Shikra Driver"); -MODULE_LICENSE("GPL"); diff --git a/include/dt-bindings/clock/qcom,shikra-dispcc.h b/include/dt-bindings/clock/qcom,shikra-dispcc.h deleted file mode 100644 index 088a7c692ad5d..0000000000000 --- a/include/dt-bindings/clock/qcom,shikra-dispcc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_SHIKRA_H -#define _DT_BINDINGS_CLK_QCOM_DISP_CC_SHIKRA_H - -/* DISP_CC clocks */ -#define DISP_CC_PLL0 0 -#define DISP_CC_MDSS_AHB_CLK 1 -#define DISP_CC_MDSS_AHB_CLK_SRC 2 -#define DISP_CC_MDSS_BYTE0_CLK 3 -#define DISP_CC_MDSS_BYTE0_CLK_SRC 4 -#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 5 -#define DISP_CC_MDSS_BYTE0_INTF_CLK 6 -#define DISP_CC_MDSS_ESC0_CLK 7 -#define DISP_CC_MDSS_ESC0_CLK_SRC 8 -#define DISP_CC_MDSS_MDP_CLK 9 -#define DISP_CC_MDSS_MDP_CLK_SRC 10 -#define DISP_CC_MDSS_MDP_LUT_CLK 11 -#define DISP_CC_MDSS_NON_GDSC_AHB_CLK 12 -#define DISP_CC_MDSS_PCLK0_CLK 13 -#define DISP_CC_MDSS_PCLK0_CLK_SRC 14 -#define DISP_CC_MDSS_VSYNC_CLK 15 -#define DISP_CC_MDSS_VSYNC_CLK_SRC 16 -#define DISP_CC_SLEEP_CLK 17 -#define DISP_CC_SLEEP_CLK_SRC 18 -#define DISP_CC_XO_CLK 19 -#define DISP_CC_XO_CLK_SRC 20 - -/* DISP_CC power domains */ -#define DISP_CC_MDSS_CORE_GDSC 0 - -/* DISP_CC resets */ -#define DISP_CC_MDSS_CORE_BCR 0 -#define DISP_CC_MDSS_RSCC_BCR 1 - -#endif diff --git a/include/dt-bindings/clock/qcom,shikra-gpucc.h b/include/dt-bindings/clock/qcom,shikra-gpucc.h deleted file mode 100644 index 60714f6cc6cd2..0000000000000 --- a/include/dt-bindings/clock/qcom,shikra-gpucc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SHIKRA_H -#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SHIKRA_H - -/* GPU_CC clocks */ -#define GPU_CC_PLL0 0 -#define GPU_CC_AHB_CLK 1 -#define GPU_CC_CRC_AHB_CLK 2 -#define GPU_CC_CX_GFX3D_CLK 3 -#define GPU_CC_CX_GFX3D_SLV_CLK 4 -#define GPU_CC_CX_GMU_CLK 5 -#define GPU_CC_CX_SNOC_DVM_CLK 6 -#define GPU_CC_CXO_AON_CLK 7 -#define GPU_CC_CXO_CLK 8 -#define GPU_CC_GMU_CLK_SRC 9 -#define GPU_CC_GPU_SMMU_VOTE_CLK 10 -#define GPU_CC_GX_CXO_CLK 11 -#define GPU_CC_GX_GFX3D_CLK 12 -#define GPU_CC_GX_GFX3D_CLK_SRC 13 -#define GPU_CC_SLEEP_CLK 14 - -/* GPU_CC power domains */ -#define GPU_CC_CX_GDSC 0 -#define GPU_CC_GX_GDSC 1 - -/* GPU_CC resets */ -#define GPU_CC_CX_BCR 0 -#define GPU_CC_GFX3D_AON_BCR 1 -#define GPU_CC_GMU_BCR 2 -#define GPU_CC_GX_BCR 3 -#define GPU_CC_XO_BCR 4 - -#endif From d2e83ed644bdb27062640bf1544372a73224f431 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:23 +0530 Subject: [PATCH 0981/1058] clk: qcom: gcc-qcm2290: Keep the critical clocks always-on from probe Some GCC branch clocks are required to be kept always-on due to the hardware requirements. Drop the modelling of those always-on QCM2290 GCC clocks and use the latest .clk_cbcr convention to keep them enabled from probe. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gcc-qcm2290.c | 160 ++++----------------------------- 1 file changed, 18 insertions(+), 142 deletions(-) diff --git a/drivers/clk/qcom/gcc-qcm2290.c b/drivers/clk/qcom/gcc-qcm2290.c index 6684cab63ae11..8751e057d8973 100644 --- a/drivers/clk/qcom/gcc-qcm2290.c +++ b/drivers/clk/qcom/gcc-qcm2290.c @@ -1397,36 +1397,6 @@ static struct clk_branch gcc_cam_throttle_rt_clk = { }, }; -static struct clk_branch gcc_camera_ahb_clk = { - .halt_reg = 0x17008, - .halt_check = BRANCH_HALT_DELAY, - .hwcg_reg = 0x17008, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x17008, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_camera_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gcc_camera_xo_clk = { - .halt_reg = 0x17028, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x17028, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_camera_xo_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_camss_axi_clk = { .halt_reg = 0x58044, .halt_check = BRANCH_HALT, @@ -1825,22 +1795,6 @@ static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { }, }; -static struct clk_branch gcc_disp_ahb_clk = { - .halt_reg = 0x1700c, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x1700c, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x1700c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_disp_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_regmap_div gcc_disp_gpll0_clk_src = { .reg = 0x17058, .shift = 0, @@ -1899,20 +1853,6 @@ static struct clk_branch gcc_disp_throttle_core_clk = { }, }; -static struct clk_branch gcc_disp_xo_clk = { - .halt_reg = 0x1702c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x1702c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_disp_xo_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x4d000, .halt_check = BRANCH_HALT, @@ -1964,22 +1904,6 @@ static struct clk_branch gcc_gp3_clk = { }, }; -static struct clk_branch gcc_gpu_cfg_ahb_clk = { - .halt_reg = 0x36004, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x36004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x36004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_gpu_cfg_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gpu_gpll0_clk_src = { .halt_check = BRANCH_HALT_DELAY, .clkr = { @@ -2012,19 +1936,6 @@ static struct clk_branch gcc_gpu_gpll0_div_clk_src = { }, }; -static struct clk_branch gcc_gpu_iref_clk = { - .halt_reg = 0x36100, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x36100, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_gpu_iref_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gpu_memnoc_gfx_clk = { .halt_reg = 0x3600c, .halt_check = BRANCH_VOTED, @@ -2439,22 +2350,6 @@ static struct clk_branch gcc_sdcc2_apps_clk = { }, }; -static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { - .halt_reg = 0x2b06c, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x2b06c, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x79004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_sys_noc_cpuss_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { .halt_reg = 0x1a080, .halt_check = BRANCH_HALT, @@ -2605,21 +2500,6 @@ static struct clk_branch gcc_venus_ctl_axi_clk = { }, }; -static struct clk_branch gcc_video_ahb_clk = { - .halt_reg = 0x17004, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x17004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x17004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_video_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_video_axi0_clk = { .halt_reg = 0x1701c, .halt_check = BRANCH_HALT, @@ -2686,19 +2566,6 @@ static struct clk_branch gcc_video_venus_ctl_clk = { }, }; -static struct clk_branch gcc_video_xo_clk = { - .halt_reg = 0x17024, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x17024, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_video_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct gdsc gcc_camss_top_gdsc = { .gdscr = 0x58004, .pd = { @@ -2775,8 +2642,6 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, [GCC_CAM_THROTTLE_NRT_CLK] = &gcc_cam_throttle_nrt_clk.clkr, [GCC_CAM_THROTTLE_RT_CLK] = &gcc_cam_throttle_rt_clk.clkr, - [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, - [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, [GCC_CAMSS_AXI_CLK] = &gcc_camss_axi_clk.clkr, [GCC_CAMSS_AXI_CLK_SRC] = &gcc_camss_axi_clk_src.clkr, [GCC_CAMSS_CAMNOC_ATB_CLK] = &gcc_camss_camnoc_atb_clk.clkr, @@ -2817,22 +2682,18 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, [GCC_CAMSS_TOP_AHB_CLK_SRC] = &gcc_camss_top_ahb_clk_src.clkr, [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, - [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr, [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr, [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, - [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, - [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, - [GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr, [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, @@ -2870,7 +2731,6 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, - [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, @@ -2887,13 +2747,11 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr, [GCC_VENUS_AHB_CLK] = &gcc_venus_ahb_clk.clkr, [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr, - [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr, [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr, [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr, [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, - [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, [GPLL0] = &gpll0.clkr, [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr, [GPLL1] = &gpll1.clkr, @@ -2943,6 +2801,18 @@ static struct gdsc *gcc_qcm2290_gdscs[] = { [HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc, }; +static u32 gcc_qcm2290_critical_cbcrs[] = { + 0x17008, /* GCC_CAMERA_AHB_CLK */ + 0x17028, /* GCC_CAMERA_XO_CLK */ + 0x1700c, /* GCC_DISP_AHB_CLK */ + 0x1702c, /* GCC_DISP_XO_CLK */ + 0x36004, /* GCC_GPU_CFG_AHB_CLK */ + 0x36100, /* GCC_GPU_IREF_CLK */ + 0x79004, /* GCC_SYS_NOC_CPUSS_AHB_CLK */ + 0x17004, /* GCC_VIDEO_AHB_CLK */ + 0x17024, /* GCC_VIDEO_XO_CLK */ +}; + static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), @@ -2960,6 +2830,11 @@ static const struct regmap_config gcc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data gcc_qcm2290_driver_data = { + .clk_cbcrs = gcc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gcc_qcm2290_critical_cbcrs), +}; + static const struct qcom_cc_desc gcc_qcm2290_desc = { .config = &gcc_qcm2290_regmap_config, .clks = gcc_qcm2290_clocks, @@ -2968,6 +2843,7 @@ static const struct qcom_cc_desc gcc_qcm2290_desc = { .num_resets = ARRAY_SIZE(gcc_qcm2290_resets), .gdscs = gcc_qcm2290_gdscs, .num_gdscs = ARRAY_SIZE(gcc_qcm2290_gdscs), + .driver_data = &gcc_qcm2290_driver_data, }; static const struct of_device_id gcc_qcm2290_match_table[] = { From 33c2480f8e65a02500004738d1f86c710730953e Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:24 +0530 Subject: [PATCH 0982/1058] dt-bindings: clock: qcom,qcm2290-dispcc: Add DSI1 PHY and sleep clocks Update the QCM2290 DISPCC binding to document additional clock inputs supported by the hardware, including DSI1 PHY byte/pixel clocks and the sleep clock, alongside the existing clock list. This is an ABI extension, and existing clock inputs ordering is unchanged. Signed-off-by: Imran Shaik --- .../bindings/clock/qcom,qcm2290-dispcc.yaml | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml index 4a533b45eec2d..24f2cce033f6e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml @@ -25,8 +25,11 @@ properties: - description: Board active-only XO source - description: GPLL0 source from GCC - description: GPLL0 div source from GCC - - description: Byte clock from DSI PHY - - description: Pixel clock from DSI PHY + - description: Byte clock from DSI PHY0 + - description: Pixel clock from DSI PHY0 + - description: Byte clock from DSI PHY1 + - description: Pixel clock from DSI PHY1 + - description: Board sleep clock clock-names: items: @@ -36,6 +39,9 @@ properties: - const: gcc_disp_gpll0_div_clk_src - const: dsi0_phy_pll_out_byteclk - const: dsi0_phy_pll_out_dsiclk + - const: dsi1_phy_pll_out_byteclk + - const: dsi1_phy_pll_out_dsiclk + - const: sleep_clk required: - compatible @@ -61,13 +67,19 @@ examples: <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, <&dsi0_phy 0>, - <&dsi0_phy 1>; + <&dsi0_phy 1>, + <&dsi1_phy 0>, + <&dsi1_phy 1>, + <&sleep_clk>; clock-names = "bi_tcxo", "bi_tcxo_ao", "gcc_disp_gpll0_clk_src", "gcc_disp_gpll0_div_clk_src", "dsi0_phy_pll_out_byteclk", - "dsi0_phy_pll_out_dsiclk"; + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From 2b08795a8246f525fcc8a6579b28a5ddaa2e4eb5 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:25 +0530 Subject: [PATCH 0983/1058] dt-bindings: clock: qcom: Add Qualcomm Shikra Display clock controller The Qualcomm Shikra Display clock controller is similar to QCM2290 DISPCC hardware block. Hence, reuse the QCM2290 DISPCC bindings for Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- .../devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml index 24f2cce033f6e..5cee033f2115d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml @@ -17,7 +17,13 @@ description: | properties: compatible: - const: qcom,qcm2290-dispcc + oneOf: + - items: + - enum: + - qcom,shikra-dispcc + - const: qcom,qcm2290-dispcc + - enum: + - qcom,qcm2290-dispcc clocks: items: From 255a2994d00d4edbf0728da2af57d9b357a29759 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:26 +0530 Subject: [PATCH 0984/1058] dt-bindings: clock: qcom: Add Qualcomm Shikra GPU clock controller The Qualcomm Shikra GPU clock controller is similar to QCM2290 GPUCC hardware block, with minor differences. Hence, reuse the QCM2290 GPUCC bindings for Qualcomm Shikra SoC. Signed-off-by: Imran Shaik --- .../devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml index 734880805c1b9..1bd70d091fcd7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml @@ -18,7 +18,9 @@ description: | properties: compatible: - const: qcom,qcm2290-gpucc + enum: + - qcom,qcm2290-gpucc + - qcom,shikra-gpucc reg: maxItems: 1 From c1eb43225892654a04ea702331aeec888590c80d Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:27 +0530 Subject: [PATCH 0985/1058] clk: qcom: dispcc-qcm2290: Move to the latest common qcom_cc_probe() model Update the QCM2290 DISPCC driver to use the qcom_cc_probe() model by moving the critical clocks handling and PLL configurations from probe to the driver_data to align with the latest convention. Signed-off-by: Imran Shaik --- drivers/clk/qcom/dispcc-qcm2290.c | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c index 6d88d067337fa..6862528a65aa8 100644 --- a/drivers/clk/qcom/dispcc-qcm2290.c +++ b/drivers/clk/qcom/dispcc-qcm2290.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * Copyright (c) 2021, Linaro Ltd. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -49,6 +50,7 @@ static const struct alpha_pll_config disp_cc_pll0_config = { static struct clk_alpha_pll disp_cc_pll0 = { .offset = 0x0, + .config = &disp_cc_pll0_config, .vco_table = spark_vco, .num_vco = ARRAY_SIZE(spark_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], @@ -483,6 +485,14 @@ static struct clk_regmap *disp_cc_qcm2290_clocks[] = { [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, }; +static struct clk_alpha_pll *disp_cc_qcm2290_plls[] = { + &disp_cc_pll0, +}; + +static u32 disp_cc_qcm2290_critical_cbcrs[] = { + 0x604c, /* DISP_CC_XO_CLK */ +}; + static const struct regmap_config disp_cc_qcm2290_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -491,6 +501,13 @@ static const struct regmap_config disp_cc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data disp_cc_qcm2290_driver_data = { + .alpha_plls = disp_cc_qcm2290_plls, + .num_alpha_plls = ARRAY_SIZE(disp_cc_qcm2290_plls), + .clk_cbcrs = disp_cc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(disp_cc_qcm2290_critical_cbcrs), +}; + static const struct qcom_cc_desc disp_cc_qcm2290_desc = { .config = &disp_cc_qcm2290_regmap_config, .clks = disp_cc_qcm2290_clocks, @@ -499,6 +516,7 @@ static const struct qcom_cc_desc disp_cc_qcm2290_desc = { .num_gdscs = ARRAY_SIZE(disp_cc_qcm2290_gdscs), .resets = disp_cc_qcm2290_resets, .num_resets = ARRAY_SIZE(disp_cc_qcm2290_resets), + .driver_data = &disp_cc_qcm2290_driver_data, }; static const struct of_device_id disp_cc_qcm2290_match_table[] = { @@ -509,25 +527,7 @@ MODULE_DEVICE_TABLE(of, disp_cc_qcm2290_match_table); static int disp_cc_qcm2290_probe(struct platform_device *pdev) { - struct regmap *regmap; - int ret; - - regmap = qcom_cc_map(pdev, &disp_cc_qcm2290_desc); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - clk_alpha_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); - - /* Keep some clocks always-on */ - qcom_branch_set_clk_en(regmap, 0x604c); /* DISP_CC_XO_CLK */ - - ret = qcom_cc_really_probe(&pdev->dev, &disp_cc_qcm2290_desc, regmap); - if (ret) { - dev_err(&pdev->dev, "Failed to register DISP CC clocks\n"); - return ret; - } - - return ret; + return qcom_cc_probe(pdev, &disp_cc_qcm2290_desc); } static struct platform_driver disp_cc_qcm2290_driver = { From cea775a669454ae608bb8208b4f415c5856f275a Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:28 +0530 Subject: [PATCH 0986/1058] clk: qcom: dispcc-qcm2290: Switch to DT index based clk lookup Update the QCM2290 DISPCC driver to use the DT index based parent clock lookup to align with the latest convention. While at it, fix the parent data of mdss ahb/mdp clocks to use GPLL0 main output as per HW clock plan, and update frequency table accordingly. Also, add the DSI1 PHY PLL input clocks support. Signed-off-by: Imran Shaik --- drivers/clk/qcom/dispcc-qcm2290.c | 44 +++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c index 6862528a65aa8..bac05730f24a3 100644 --- a/drivers/clk/qcom/dispcc-qcm2290.c +++ b/drivers/clk/qcom/dispcc-qcm2290.c @@ -24,6 +24,18 @@ #include "gdsc.h" #include "reset.h" +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_GPLL0_OUT_DIV, + DT_GPLL0, + DT_DSI0_PHY_PLL_OUT_BYTECLK, + DT_DSI0_PHY_PLL_OUT_DSICLK, + DT_DSI1_PHY_PLL_OUT_BYTECLK, + DT_DSI1_PHY_PLL_OUT_DSICLK, + DT_SLEEP_CLK, +}; + enum { P_BI_TCXO, P_BI_TCXO_AO, @@ -33,6 +45,8 @@ enum { P_GPLL0_OUT_DIV, P_GPLL0_OUT_MAIN, P_SLEEP_CLK, + P_DSI1_PHY_PLL_OUT_BYTECLK, + P_DSI1_PHY_PLL_OUT_DSICLK, }; static const struct pll_vco spark_vco[] = { @@ -58,7 +72,7 @@ static struct clk_alpha_pll disp_cc_pll0 = { .hw.init = &(struct clk_init_data){ .name = "disp_cc_pll0", .parent_data = &(const struct clk_parent_data){ - .fw_name = "bi_tcxo", + .index = DT_BI_TCXO, }, .num_parents = 1, .ops = &clk_alpha_pll_ops, @@ -72,8 +86,8 @@ static const struct parent_map disp_cc_parent_map_0[] = { }; static const struct clk_parent_data disp_cc_parent_data_0[] = { - { .fw_name = "bi_tcxo" }, - { .fw_name = "dsi0_phy_pll_out_byteclk" }, + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, }; static const struct parent_map disp_cc_parent_map_1[] = { @@ -81,17 +95,17 @@ static const struct parent_map disp_cc_parent_map_1[] = { }; static const struct clk_parent_data disp_cc_parent_data_1[] = { - { .fw_name = "bi_tcxo" }, + { .index = DT_BI_TCXO }, }; static const struct parent_map disp_cc_parent_map_2[] = { { P_BI_TCXO_AO, 0 }, - { P_GPLL0_OUT_DIV, 4 }, + { P_GPLL0_OUT_MAIN, 4 }, }; static const struct clk_parent_data disp_cc_parent_data_2[] = { - { .fw_name = "bi_tcxo_ao" }, - { .fw_name = "gcc_disp_gpll0_div_clk_src" }, + { .index = DT_BI_TCXO_AO }, + { .index = DT_GPLL0 }, }; static const struct parent_map disp_cc_parent_map_3[] = { @@ -101,19 +115,21 @@ static const struct parent_map disp_cc_parent_map_3[] = { }; static const struct clk_parent_data disp_cc_parent_data_3[] = { - { .fw_name = "bi_tcxo" }, + { .index = DT_BI_TCXO }, { .hw = &disp_cc_pll0.clkr.hw }, - { .fw_name = "gcc_disp_gpll0_clk_src" }, + { .index = DT_GPLL0 }, }; static const struct parent_map disp_cc_parent_map_4[] = { { P_BI_TCXO, 0 }, { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, + { P_DSI1_PHY_PLL_OUT_DSICLK, 2 }, }; static const struct clk_parent_data disp_cc_parent_data_4[] = { - { .fw_name = "bi_tcxo" }, - { .fw_name = "dsi0_phy_pll_out_dsiclk" }, + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_DSICLK }, + { .index = DT_DSI1_PHY_PLL_OUT_DSICLK }, }; static const struct parent_map disp_cc_parent_map_5[] = { @@ -121,7 +137,7 @@ static const struct parent_map disp_cc_parent_map_5[] = { }; static const struct clk_parent_data disp_cc_parent_data_5[] = { - { .fw_name = "sleep_clk" }, + { .index = DT_SLEEP_CLK }, }; static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { @@ -155,8 +171,8 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { F(19200000, P_BI_TCXO_AO, 1, 0, 0), - F(37500000, P_GPLL0_OUT_DIV, 8, 0, 0), - F(75000000, P_GPLL0_OUT_DIV, 4, 0, 0), + F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0), { } }; From 46df16b8691753200c18f2ecff21b2b2b4ad8435 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:29 +0530 Subject: [PATCH 0987/1058] clk: qcom: dispcc-qcm2290: Update GDSC *wait_val values and flags Update the QCM2290 DISPCC GDSC wait_val fields to match the hardware default values. Incorrect settings can cause the GDSC FSM to stuck, leading to power on/off failures. And update GDSC flags to retain the registers, and poll for the CFG GDSCR, and switch between HW/SW mode dynamically as per the latest convention. Signed-off-by: Imran Shaik --- drivers/clk/qcom/dispcc-qcm2290.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c index bac05730f24a3..5109c8e0f4add 100644 --- a/drivers/clk/qcom/dispcc-qcm2290.c +++ b/drivers/clk/qcom/dispcc-qcm2290.c @@ -468,11 +468,14 @@ static const struct qcom_reset_map disp_cc_qcm2290_resets[] = { static struct gdsc mdss_gdsc = { .gdscr = 0x3000, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "mdss_gdsc", }, .pwrsts = PWRSTS_OFF_ON, - .flags = HW_CTRL, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; static struct gdsc *disp_cc_qcm2290_gdscs[] = { From f78839dcd0b405371786dda30b7047c562e1bbbe Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:30 +0530 Subject: [PATCH 0988/1058] clk: qcom: gpucc-qcm2290: Move to the latest common qcom_cc_probe() model Update the QCM2290 GPUCC driver to use the qcom_cc_probe() model by moving the critical clocks handling and PLL configurations from probe to the driver_data to align with the latest convention. While at it, drop the modelling of gpu_cc_ahb_clk and gpu_cc_cxo_aon_clk clocks and keep them enabled from probe as per the hardware requirements, and drop pm_clk handling as the required GCC clocks are kept always-on from GCC probe. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gpucc-qcm2290.c | 92 ++++++++------------------------ 1 file changed, 21 insertions(+), 71 deletions(-) diff --git a/drivers/clk/qcom/gpucc-qcm2290.c b/drivers/clk/qcom/gpucc-qcm2290.c index dc369dff882e6..242f2b0ea53c6 100644 --- a/drivers/clk/qcom/gpucc-qcm2290.c +++ b/drivers/clk/qcom/gpucc-qcm2290.c @@ -2,14 +2,13 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * Copyright (c) 2024, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include #include #include #include -#include -#include #include #include @@ -20,7 +19,7 @@ #include "clk-regmap.h" #include "clk-regmap-divider.h" #include "clk-regmap-mux.h" -#include "clk-regmap-phy-mux.h" +#include "common.h" #include "gdsc.h" #include "reset.h" @@ -57,6 +56,7 @@ static const struct alpha_pll_config gpu_cc_pll0_config = { static struct clk_alpha_pll gpu_cc_pll0 = { .offset = 0x0, + .config = &gpu_cc_pll0_config, .vco_table = huayra_vco, .num_vco = ARRAY_SIZE(huayra_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], @@ -148,20 +148,6 @@ static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { }, }; -static struct clk_branch gpu_cc_ahb_clk = { - .halt_reg = 0x1078, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x1078, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpu_cc_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gpu_cc_crc_ahb_clk = { .halt_reg = 0x107c, .halt_check = BRANCH_HALT_DELAY, @@ -224,19 +210,6 @@ static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { }, }; -static struct clk_branch gpu_cc_cxo_aon_clk = { - .halt_reg = 0x1004, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x1004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpu_cc_cxo_aon_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gpu_cc_cxo_clk = { .halt_reg = 0x109c, .halt_check = BRANCH_HALT, @@ -318,12 +291,10 @@ static struct gdsc gpu_gx_gdsc = { }; static struct clk_regmap *gpu_cc_qcm2290_clocks[] = { - [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, - [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, @@ -342,6 +313,16 @@ static struct gdsc *gpu_cc_qcm2290_gdscs[] = { [GPU_GX_GDSC] = &gpu_gx_gdsc, }; +static struct clk_alpha_pll *gpu_cc_qcm2290_plls[] = { + &gpu_cc_pll0, +}; + +static u32 gpu_cc_qcm2290_critical_cbcrs[] = { + 0x1078, /* GPU_CC_AHB_CLK */ + 0x1004, /* GPU_CC_CXO_AON_CLK */ + 0x1060, /* GPU_CC_GX_CXO_CLK */ +}; + static const struct regmap_config gpu_cc_qcm2290_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -350,6 +331,12 @@ static const struct regmap_config gpu_cc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data gpu_cc_qcm2290_driver_data = { + .alpha_plls = gpu_cc_qcm2290_plls, + .num_alpha_plls = ARRAY_SIZE(gpu_cc_qcm2290_plls), + .clk_cbcrs = gpu_cc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_qcm2290_critical_cbcrs), +}; static const struct qcom_cc_desc gpu_cc_qcm2290_desc = { .config = &gpu_cc_qcm2290_regmap_config, @@ -359,6 +346,7 @@ static const struct qcom_cc_desc gpu_cc_qcm2290_desc = { .num_resets = ARRAY_SIZE(gpu_cc_qcm2290_resets), .gdscs = gpu_cc_qcm2290_gdscs, .num_gdscs = ARRAY_SIZE(gpu_cc_qcm2290_gdscs), + .driver_data = &gpu_cc_qcm2290_driver_data, }; static const struct of_device_id gpu_cc_qcm2290_match_table[] = { @@ -369,45 +357,7 @@ MODULE_DEVICE_TABLE(of, gpu_cc_qcm2290_match_table); static int gpu_cc_qcm2290_probe(struct platform_device *pdev) { - struct regmap *regmap; - int ret; - - regmap = qcom_cc_map(pdev, &gpu_cc_qcm2290_desc); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - ret = devm_pm_runtime_enable(&pdev->dev); - if (ret) - return ret; - - ret = devm_pm_clk_create(&pdev->dev); - if (ret) - return ret; - - ret = pm_clk_add(&pdev->dev, NULL); - if (ret < 0) { - dev_err(&pdev->dev, "failed to acquire ahb clock\n"); - return ret; - } - - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret) - return ret; - - clk_huayra_2290_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); - - regmap_update_bits(regmap, 0x1060, BIT(0), BIT(0)); /* GPU_CC_GX_CXO_CLK */ - - ret = qcom_cc_really_probe(&pdev->dev, &gpu_cc_qcm2290_desc, regmap); - if (ret) { - dev_err(&pdev->dev, "Failed to register display clock controller\n"); - goto out_pm_runtime_put; - } - -out_pm_runtime_put: - pm_runtime_put_sync(&pdev->dev); - - return 0; + return qcom_cc_probe(pdev, &gpu_cc_qcm2290_desc); } static struct platform_driver gpu_cc_qcm2290_driver = { From d15cc0e6288f1fd5510808e6e7400908f1a9a22b Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:31 +0530 Subject: [PATCH 0989/1058] clk: qcom: gpucc-qcm2290: Park RCG's clk source at XO during disable The RCG's clk src has to be parked at XO while disabling as per the HW recommendation, hence use clk_rcg2_shared_ops to achieve the same. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gpucc-qcm2290.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gpucc-qcm2290.c b/drivers/clk/qcom/gpucc-qcm2290.c index 242f2b0ea53c6..c76015e05d455 100644 --- a/drivers/clk/qcom/gpucc-qcm2290.c +++ b/drivers/clk/qcom/gpucc-qcm2290.c @@ -144,7 +144,7 @@ static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { .parent_data = gpu_cc_parent_data_1, .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; From cee5170c5cdc20e0ec46dade963f52bdbb73b1d7 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:32 +0530 Subject: [PATCH 0990/1058] clk: qcom: gpucc-qcm2290: Update GDSC *wait_val values and flags Update the QCM2290 GPUCC GDSC wait_val fields to match the hardware default values. Incorrect settings can cause the GDSC FSM to stuck, leading to power on/off failures. And update the GPUCC GDSC flags to retain the registers, and poll for the CFG GDSCR as applicable. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gpucc-qcm2290.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/gpucc-qcm2290.c b/drivers/clk/qcom/gpucc-qcm2290.c index c76015e05d455..67e3ccb1ccf72 100644 --- a/drivers/clk/qcom/gpucc-qcm2290.c +++ b/drivers/clk/qcom/gpucc-qcm2290.c @@ -270,11 +270,14 @@ static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { static struct gdsc gpu_cx_gdsc = { .gdscr = 0x106c, .gds_hw_ctrl = 0x1540, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, .pd = { .name = "gpu_cx_gdsc", }, .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, + .flags = RETAIN_FF_ENABLE | VOTABLE, }; static struct gdsc gpu_gx_gdsc = { @@ -282,12 +285,15 @@ static struct gdsc gpu_gx_gdsc = { .clamp_io_ctrl = 0x1508, .resets = (unsigned int []){ GPU_GX_BCR }, .reset_count = 1, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, .pd = { .name = "gpu_gx_gdsc", }, .parent = &gpu_cx_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, - .flags = CLAMP_IO | AON_RESET | SW_RESET, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | SW_RESET | CLAMP_IO | AON_RESET, }; static struct clk_regmap *gpu_cc_qcm2290_clocks[] = { From cd88b5dc3dc72d27a07606186ac46cb3817fba46 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 1 Jun 2026 23:51:33 +0530 Subject: [PATCH 0991/1058] clk: qcom: Add support for Qualcomm GPU Clock Controller on Shikra The Qualcomm Shikra GPU clock controller is similar to QCM2290 GPUCC hardware block, with minor differences. Hence add support for Shikra GPUCC by extending the QCM2290 GPUCC driver. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gpucc-qcm2290.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/qcom/gpucc-qcm2290.c b/drivers/clk/qcom/gpucc-qcm2290.c index 67e3ccb1ccf72..92d55839ad1e6 100644 --- a/drivers/clk/qcom/gpucc-qcm2290.c +++ b/drivers/clk/qcom/gpucc-qcm2290.c @@ -133,6 +133,17 @@ static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src_shikra[] = { + F(355200000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(537600000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(672000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(844800000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(921600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1017600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1142400000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + { } +}; + static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { .cmd_rcgr = 0x101c, .mnd_width = 0, @@ -357,12 +368,16 @@ static const struct qcom_cc_desc gpu_cc_qcm2290_desc = { static const struct of_device_id gpu_cc_qcm2290_match_table[] = { { .compatible = "qcom,qcm2290-gpucc" }, + { .compatible = "qcom,shikra-gpucc" }, { } }; MODULE_DEVICE_TABLE(of, gpu_cc_qcm2290_match_table); static int gpu_cc_qcm2290_probe(struct platform_device *pdev) { + if (device_is_compatible(&pdev->dev, "qcom,shikra-gpucc")) + gpu_cc_gx_gfx3d_clk_src.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src_shikra; + return qcom_cc_probe(pdev, &gpu_cc_qcm2290_desc); } From 70442a0f2800218ad4052aa87414673a4e17de08 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Fri, 29 May 2026 12:53:22 +0530 Subject: [PATCH 0992/1058] dt-bindings: sound: qcom: add Shikra QAIF Document the QAIF CPU DAI controller binding used by Shikra audio. Signed-off-by: Mohammad Rafi Shaik --- .../bindings/sound/qcom,shikra-qaif.yaml | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml b/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml new file mode 100644 index 0000000000000..640dc5f86b198 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,shikra-qaif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Audio Interface on Shikra + +maintainers: + - Qualcomm Innovation Center, Inc. + +description: + Qualcomm Audio Interface CPU DAI controller used by the Shikra audio core. + +properties: + compatible: + const: qcom,shikra-qaif-cpu + + reg: + maxItems: 1 + + reg-names: + const: audio-qaif-core + + iommus: + maxItems: 1 + + clocks: + minItems: 15 + maxItems: 15 + + clock-names: + items: + - const: gcc_lpass_config_clk + - const: gcc_lpass_core_axim_clk + - const: audio_core_cc_aud_dma_clk + - const: audio_core_cc_aud_dma_mem_clk + - const: audio_core_cc_bus_clk + - const: audio_core_cc_aif_if0_ebit_clk + - const: audio_core_cc_aif_if0_ibit_clk + - const: audio_core_cc_aif_if1_ebit_clk + - const: audio_core_cc_aif_if1_ibit_clk + - const: audio_core_cc_aif_if2_ebit_clk + - const: audio_core_cc_aif_if2_ibit_clk + - const: audio_core_cc_aif_if3_ebit_clk + - const: audio_core_cc_aif_if3_ibit_clk + - const: audio_core_cc_ext_mclka_clk + - const: audio_core_cc_ext_mclkb_clk + + interrupts: + maxItems: 1 + + interrupt-names: + const: qaif-irq-audio-core + + '#sound-dai-cells': + const: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + aif-interface: + $ref: /schemas/types.yaml#/definitions/phandle + description: TDM/MI2S interface configuration referenced by this controller. + +required: + - compatible + - reg + - reg-names + - iommus + - clocks + - clock-names + - interrupts + - interrupt-names + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + #include + #include + #include + + audio@a000000 { + compatible = "qcom,shikra-qaif-cpu"; + reg = <0x0a000000 0x20000>; + reg-names = "audio-qaif-core"; + iommus = <&apps_smmu 0x1c0 0x0>; + clocks = <&gcc 0>, <&gcc 1>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK>; + clock-names = "gcc_lpass_config_clk", "gcc_lpass_core_axim_clk", + "audio_core_cc_aud_dma_clk", + "audio_core_cc_aud_dma_mem_clk", + "audio_core_cc_bus_clk", + "audio_core_cc_aif_if0_ebit_clk", + "audio_core_cc_aif_if0_ibit_clk", + "audio_core_cc_aif_if1_ebit_clk", + "audio_core_cc_aif_if1_ibit_clk", + "audio_core_cc_aif_if2_ebit_clk", + "audio_core_cc_aif_if2_ibit_clk", + "audio_core_cc_aif_if3_ebit_clk", + "audio_core_cc_aif_if3_ibit_clk", + "audio_core_cc_ext_mclka_clk", + "audio_core_cc_ext_mclkb_clk"; + interrupts = ; + interrupt-names = "qaif-irq-audio-core"; + #sound-dai-cells = <1>; + }; + +... From 3aae88da425e3b52ada28cd73ce617a1d60d9cb8 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Fri, 29 May 2026 11:43:15 +0530 Subject: [PATCH 0993/1058] ASoC: qcom: add QAIF header files Add the QAIF header files for shikra SOC. This includes the register definitions for the shikra QAIF, and the structure definition for the driver data. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/qaif-reg.h | 689 ++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qaif.h | 576 +++++++++++++++++++++++++++++++ 2 files changed, 1265 insertions(+) create mode 100644 sound/soc/qcom/qaif-reg.h create mode 100644 sound/soc/qcom/qaif.h diff --git a/sound/soc/qcom/qaif-reg.h b/sound/soc/qcom/qaif-reg.h new file mode 100644 index 0000000000000..cccee76a74861 --- /dev/null +++ b/sound/soc/qcom/qaif-reg.h @@ -0,0 +1,689 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-reg.h -- ALSA SoC CPU-Platform DAI driver register header file for QTi QAIF + */ +#ifndef __QAIF_REG_H__ +#define __QAIF_REG_H__ + +#include "qaif.h" + +#define QAIF_REG_ADDR(offset) (offset) +/* Base for AUDIO_CORE_QAIF_HW_VERSION 0xA000000 */ + +#define QAIF_SUMMARY_IRQSTAT_REG(v) \ + (0x19188 + (0x1000 * ((v)->ee))) /* 0xA019188 */ +/* + * #define QAIF_RDDMA_UNDERFLOW_REG(v) + * QAIF_REG_ADDR(0x19188 + (0x1000 * (ee))) + */ + +/* Shikra core registers */ + +/* Core HW info */ +#define QAIF_HW_VERSION_REG() (0x0000) /* 0xA000000 */ +#define QAIF_HW_INFO_REG (0x0004) /* 0xA000004 */ +#define QAIF_HW_INFO2_REG (0x0008) /* 0xA000008 */ + +/* Interface lane and channel info */ +#define QAIF_AUD_INTF_LANE_INFO_REG (0x0020) /* 0xA000020 */ +#define QAIF_AUD_INTF_LANE_INFO2_REG (0x0024) /* 0xA000024 */ +/* 0xA000028 .. 0xA000044 (n:0..7) */ +#define QAIF_CODEC_TX_INTF_CH_INFO_REG(n) (0x0028 + (0x4 * (n))) +/* 0xA000068 .. 0xA000084 (n:0..7) */ +#define QAIF_CODEC_RX_INTF_CH_INFO_REG(n) (0x0068 + (0x4 * (n))) +#define QAIF_QXM1_SHRAM_LENGTH_INFO_REG (0x0088) /* 0xA000088 */ +#define QAIF_QXM0_SHRAM_LENGTH_INFO_REG (0x008C) /* 0xA00008C */ +#define QAIF_NUM_AUD_INTF_TO_RAIL_INFO_REG (0x0090) /* 0xA000090 */ + +/* Debug/control and status */ +#define QAIF_DEBUG_CTL_REG (0x0200) /* 0xA000200 */ +#define QAIF_WRDMA_LOOPBACK_EN_REG (0x0204) /* 0xA000204 */ +#define QAIF_WRDMA_LOOPBACK_SEL_REG (0x0208) /* 0xA000208 */ +#define QAIF_SHRAM_DYNAMIC_CLK_GATING_EN_REG (0x0300) /* 0xA000300 */ +#define QAIF_AXI_STATUS_REG (0x0304) /* 0xA000304 */ +#define QAIF_QSB_DYNAMIC_CLK_GATING_EN_REG (0x0308) /* 0xA000308 */ +#define QAIF_START_STOP_CTRL_BYPASS_EN_REG (0x030C) /* 0xA00030C */ +#define QAIF_QXM0_AXI_ATTR_CFG_REG (0x040C) /* 0xA00040C */ + +/* QXM request/grant debug */ +#define QAIF_QXM0_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0500) /* 0xA000500 */ +#define QAIF_QXM1_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0504) /* 0xA000504 */ +#define QAIF_QXM0_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0508) /* 0xA000508 */ +#define QAIF_QXM0_CODEC_RX_WR_GNT_DBG_STAT_REG (0x050C) /* 0xA00050C */ +#define QAIF_QXM1_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0510) /* 0xA000510 */ +#define QAIF_QXM1_CODEC_RX_WR_GNT_DBG_STAT_REG (0x0514) /* 0xA000514 */ +#define QAIF_QXM0_AUD_RD_REQ_GNT_DBG_STAT_REG (0x0518) /* 0xA000518 */ +#define QAIF_QXM1_AUD_RD_REQ_GNT_DBG_STAT_REG (0x051C) /* 0xA00051C */ +#define QAIF_QXM0_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0520) /* 0xA000520 */ +#define QAIF_QXM0_CODEC_TX_RD_GNT_DBG_STAT_REG (0x0524) /* 0xA000524 */ +#define QAIF_QXM1_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0528) /* 0xA000528 */ +#define QAIF_QXM1_CODEC_TX_RD_GNT_DBG_STAT_REG (0x052C) /* 0xA00052C */ +#define QAIF_QXM0_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0530) /* 0xA000530 */ +#define QAIF_QXM1_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0534) /* 0xA000534 */ + +/* QSB transaction debug */ +#define QAIF_QSB_AUD_WR_TXN_DBG_STAT_REG (0x0538) /* 0xA000538 */ +#define QAIF_QSB_CODEC_RX_WR_TXN_ERR_DBG_STAT_REG (0x053C) /* 0xA00053C */ +#define QAIF_QSB_CODEC_RX_WR_TXN_OKAY_DBG_STAT_REG (0x0540) /* 0xA000540 */ +#define QAIF_QSB_AUD_ADDR_SENT_DBG_STAT_REG (0x0544) /* 0xA000544 */ +#define QAIF_QSB_CODEC_TX_RD_ADDR_SENT_DBG_STAT_REG (0x0548) /* 0xA000548 */ +#define QAIF_QSB_EXT_RDDMA_RD_ADDR_SENT_DBG_STAT_REG (0x054C) /* 0xA00054C */ +#define QAIF_QSB_CODEC_RX_WR_ADDR_SENT_DBG_STAT_REG (0x0550) /* 0xA000550 */ +#define QAIF_QSB_AUD_RD_TXN_DBG_STAT_REG (0x0554) /* 0xA000554 */ +#define QAIF_QSB_CODEC_TX_RD_TXN_ERR_DBG_STAT_REG (0x0558) /* 0xA000558 */ +#define QAIF_QSB_CODEC_TX_RD_TXN_RCVD_DBG_STAT_REG (0x055C) /* 0xA00055C */ +#define QAIF_QSB_EXT_RDDMA_RD_TXN_DBG_STAT_REG (0x0560) /* 0xA000560 */ +#define QAIF_QSB_MISC_DBG_STATUS_REG (0x0564) /* 0xA000564 */ + +/* Global spare and HWE */ +#define QAIF_GLOBAL_SPARE_IN_REG (0x0B00) /* 0xA000B00 */ +#define QAIF_GLOBAL_SPARE_OUT_REG (0x0B04) /* 0xA000B04 */ +#define QAIF_HWE_CFG_REG (0x0B08) /* 0xA000B08 */ + +/* SID maps */ +#define QAIF_WRDMA_SID_MAP_REG (0x1B00) /* 0xA001B00 */ +#define QAIF_CODEC_WRDMA_SID_MAP_REG (0x1B40) /* 0xA001B40 */ +#define QAIF_RDDMA_SID_MAP_REG (0x1C00) /* 0xA001C00 */ +#define QAIF_CODEC_RDDMA_SID_MAP_REG (0x1C40) /* 0xA001C40 */ + +/* EE overlap interrupts */ +#define QAIF_EE_OVERLAP_IRQ_EN_REG (0x1D00) /* 0xA001D00 */ +#define QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG (0x1D04) /* 0xA001D04 */ +#define QAIF_EE_OVERLAP_IRQ_CLEAR_REG (0x1D08) /* 0xA001D08 */ +#define QAIF_EE_OVERLAP_IRQ_FORCE_REG (0x1D0C) /* 0xA001D0C */ + +/* EE assignments and maps */ +/* 0xA019148 */ +#define QAIF_EE_RDDMA_ASSIGNMENT_REG(v) (0x19148 + (0x1000 * ((v)->ee))) +/* 0xA019150 */ +#define QAIF_EE_WRDMA_ASSIGNMENT_REG(v) (0x19150 + (0x1000 * ((v)->ee))) +/* 0xA019158 */ +#define QAIF_EE_INTF_ASSIGNMENT_REG(v) (0x19158 + (0x1000 * ((v)->ee))) +/* 0xA019308 */ +#define QAIF_EE_CODEC_RDDMA_ASSIGNMENT_REG(v) (0x19308 + (0x1000 * ((v)->ee))) +/* 0xA019318 */ +#define QAIF_EE_CODEC_WRDMA_ASSIGNMENT_REG(v) (0x19318 + (0x1000 * ((v)->ee))) +/* 0xA001920 */ +#define QAIF_EE_RDDMA_MAP_REG(v) (0x1920 + (0x1000 * ((v)->ee))) +/* 0xA001940 */ +#define QAIF_EE_WRDMA_MAP_REG(v) (0x1940 + (0x1000 * ((v)->ee))) +/* 0xA001960 */ +#define QAIF_EE_INTF_MAP_REG(v) (0x1960 + (0x1000 * ((v)->ee))) +/* 0xA001980 */ +#define QAIF_EE_CODEC_RDDMA_MAP_REG(v) (0x1980 + (0x1000 * ((v)->ee))) +/* 0xA001A00 */ +#define QAIF_EE_CODEC_WRDMA_MAP_REG(v) (0x1A00 + (0x1000 * ((v)->ee))) + +/* EE rate-detection and VFR interrupts */ +/* 0xA0190F0 */ +#define QAIF_EE_RATE_DET_IRQ_EN_REG(v) (0x190F0 + (0x1000 * ((v)->ee))) +/* 0xA0190F4 */ +#define QAIF_EE_RATE_DET_IRQ_STATUS_REG(v) (0x190F4 + (0x1000 * ((v)->ee))) +/* 0xA0190F8 */ +#define QAIF_EE_RATE_DET_IRQ_RAW_STATUS_REG(v) (0x190F8 + (0x1000 * ((v)->ee))) +/* 0xA0190FC */ +#define QAIF_EE_RATE_DET_IRQ_CLEAR_REG(v) (0x190FC + (0x1000 * ((v)->ee))) +/* 0xA019100 */ +#define QAIF_EE_RATE_DET_IRQ_FORCE_REG(v) (0x19100 + (0x1000 * ((v)->ee))) + +/* 0xA019104 */ +#define QAIF_EE_VFR_IRQ_EN_REG(v) (0x19104 + (0x1000 * ((v)->ee))) +/* 0xA019108 */ +#define QAIF_EE_VFR_IRQ_STATUS_REG(v) (0x19108 + (0x1000 * ((v)->ee))) +/* 0xA01910C */ +#define QAIF_EE_VFR_IRQ_RAW_STATUS_REG(v) (0x1910C + (0x1000 * ((v)->ee))) +/* 0xA019110 */ +#define QAIF_EE_VFR_IRQ_CLEAR_REG(v) (0x19110 + (0x1000 * ((v)->ee))) +/* 0xA019114 */ +#define QAIF_EE_VFR_IRQ_FORCE_REG(v) (0x19114 + (0x1000 * ((v)->ee))) + +/* EE AUD_INTF underflow/overflow interrupts */ +/* 0xA019160 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_EN_REG(v) \ + (0x19160 + (0x1000 * ((v)->ee))) +/* 0xA019164 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_STATUS_REG(v) \ + (0x19164 + (0x1000 * ((v)->ee))) +/* 0xA019168 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_RAW_STATUS_REG(v) \ + (0x19168 + (0x1000 * ((v)->ee))) +/* 0xA01916C */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_CLEAR_REG(v) \ + (0x1916C + (0x1000 * ((v)->ee))) +/* 0xA019170 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_FORCE_REG(v) \ + (0x19170 + (0x1000 * ((v)->ee))) + +/* 0xA019174 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_EN_REG(v) \ + (0x19174 + (0x1000 * ((v)->ee))) +/* 0xA019178 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_STATUS_REG(v) \ + (0x19178 + (0x1000 * ((v)->ee))) +/* 0xA01917C */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_RAW_STATUS_REG(v) \ + (0x1917C + (0x1000 * ((v)->ee))) +/* 0xA019180 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_CLEAR_REG(v) \ + (0x19180 + (0x1000 * ((v)->ee))) +/* 0xA019184 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_FORCE_REG(v) \ + (0x19184 + (0x1000 * ((v)->ee))) + +/* EE L2 Period IRQ mux selection */ +/* 0xA019F00 */ +#define QAIF_EE_L2_PERIOD_IRQ_0_3_MUX_SEL_REG(v) \ + (0x19F00 + (0x1000 * ((v)->ee))) +/* 0xA019F04 */ +#define QAIF_EE_L2_PERIOD_IRQ_4_7_MUX_SEL_REG(v) \ + (0x19F04 + (0x1000 * ((v)->ee))) + +/* AUD_INTF block (per interface, stride 0x1000 starting at 0x4000) */ +#define QAIF_AUD_INTF_REG_ADDR(offset, intf) \ + (0x4000 + (offset) + (0x1000 * (intf))) + +/* 0xA004000 */ +#define QAIF_AUD_INTF_CTL_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0000, (intf)) +/* 0xA004004 */ +#define QAIF_AUD_INTF_SYNC_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0004, (intf)) +/* 0xA004008 */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0008, (intf)) +/* 0xA00400C */ +#define QAIF_AUD_INTF_FRAME_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x000C, (intf)) +/* 0xA004010 */ +#define QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0010, (intf)) +/* 0xA004030 */ +#define QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0030, (intf)) +/* 0xA004050 */ +#define QAIF_AUD_INTF_LANE_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0050, (intf)) +/* 0xA004054 */ +#define QAIF_AUD_INTF_MI2S_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0054, (intf)) +/* 0xA004058 */ +#define QAIF_AUD_INTF_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0058, (intf)) +/* 0xA00405C */ +#define QAIF_AUD_INTF_CHAR_CTL_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x005C, (intf)) +/* 0xA004060 */ +#define QAIF_AUD_INTF_CHAR_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0060, (intf)) +/* 0xA004064 */ +#define QAIF_AUD_INTF_CHAR_DATA_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0064, (intf)) +/* 0xA004068 */ +#define QAIF_AUD_INTF_CHAR_DATA_EXT_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0068, (intf)) +/* 0xA00406C */ +#define QAIF_AUD_INTF_CHAR_SYNC_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x006C, (intf)) +/* 0xA004FF0 */ +#define QAIF_AUD_INTF_INIT_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF0, (intf)) +/* 0xA004FF4 */ +#define QAIF_AUD_INTF_TX_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF4, (intf)) +/* 0xA004FF8 */ +#define QAIF_AUD_INTF_RX_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF8, (intf)) + +/* RATE_DET block (per detector, stride 0x1000 starting at 0x1E000) */ +#define QAIF_RATE_DET_REG_ADDR(offset, det) \ + (0x1E000 + (offset) + (0x1000 * (det))) + +/* 0xA01E000 */ +#define QAIF_RATE_DET_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0000, (det)) +/* 0xA01E004 */ +#define QAIF_RATE_DET_TARGET1_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0004, (det)) +/* 0xA01E008 */ +#define QAIF_RATE_DET_TARGET2_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0008, (det)) +/* 0xA01E00C */ +#define QAIF_RATE_DET_BIN_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x000C, (det)) +/* 0xA01E010 */ +#define QAIF_RATE_DET_STC_DIFF_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0010, (det)) +/* 0xA01E014 */ +#define QAIF_RATE_DET_SEL_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0014, (det)) +/* 0xA01E018 */ +#define QAIF_RATE_DET_TIMEOUT_CFG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0018, (det)) + +#define QAIF_WRDMA_MAP_QXM (0x1000) +#define QAIF_CODEC_WRDMA_MAP_QXM (0x1004) +#define QAIF_RDDMA_MAP_QXM (0x1010) +#define QAIF_CODEC_RDDMA_MAP_QXM (0x1014) +#define QAIF_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1100 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1140 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1200 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1240 + (0x4 * (i))) +#define QAIF_RDDMA_QXM1_SHRAM_LEN(i) (0x1300 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_LEN(i) (0x1340 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_LEN(i) (0x1400 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i) (0x1440 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1500 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1540 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1600 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1640 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_LEN(i) (0x1700 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_LEN(i) (0x1740 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_LEN(i) (0x1800 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i) (0x1840 + (0x4 * (i))) + +/* + * RDDMA + * v : ptr to qaif_variant + */ +static inline u32 QAIF_RDDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->rddma_reg_base + offset + (v)->rddma_stride * chan; +} + +#define QAIF_RDDMA_CTL_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_RDDMA_CFG_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_RDDMA_BASE_ADDR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_RDDMA_BUFF_LEN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_RDDMA_CURR_ADDR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_RDDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_RDDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_RDDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_RDDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_RDDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_RDDMA_STC_LSB_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_RDDMA_STC_MSB_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_RDDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_RDDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_RDDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_RDDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_RDDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_RDDMA_PADDING_CFG_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_RDDMA_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x60, (chan)) +#define QAIF_RDDMA_DBG_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0xFF0, (chan)) + +static inline u32 QAIF_CODEC_RDDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->codec_rddma_reg_base + offset + (v)->codec_rddma_stride * chan; +} + +#define QAIF_CODEC_RDDMA_CTL_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_CODEC_RDDMA_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_CODEC_RDDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_RDDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_RDDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_RDDMA_STC_LSB_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_CODEC_RDDMA_STC_MSB_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_RDDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_CODEC_RDDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_CODEC_RDDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_RDDMA_PADDING_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_CODEC_RDDMA_INTF_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x5C, (chan)) +#define QAIF_CODEC_RDDMA_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x60, (chan)) +#define QAIF_CODEC_RDDMA_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0xFF0, (chan)) +#define QAIF_CODEC_RDDMA_INTF_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0xFF4, (chan)) + +/* + * WRDMA + * v : ptr to qaif_variant + */ +static inline u32 QAIF_WRDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->wrdma_reg_base + offset + (v)->wrdma_stride * chan; +} + +#define QAIF_WRDMA_CTL_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_WRDMA_CFG_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_WRDMA_BASE_ADDR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_WRDMA_BUFF_LEN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_WRDMA_CURR_ADDR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_WRDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_WRDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_WRDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_WRDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_WRDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_WRDMA_STC_LSB_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_WRDMA_STC_MSB_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_WRDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_WRDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_WRDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_WRDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_WRDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_WRDMA_DBG_STATUS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0xFF0, (chan)) + +static inline u32 QAIF_CODEC_WRDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->codec_wrdma_reg_base + offset + (v)->codec_wrdma_stride * chan; +} + +#define QAIF_CODEC_WRDMA_CTL_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_CODEC_WRDMA_CFG_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_CODEC_WRDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_WRDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_WRDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_WRDMA_STC_LSB_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_CODEC_WRDMA_STC_MSB_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_WRDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_CODEC_WRDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_CODEC_WRDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_WRDMA_INTF_CFG_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_CODEC_WRDMA_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0xFF0, (chan)) +#define QAIF_CODEC_WRDMA_INTF_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0xFF4, (chan)) + +static inline u32 QAIF_EE_RDDMA_IRQ_REG_ADDR(const struct qaif_variant *v, + enum qaif_irq_type_t dma_type, + u32 offset) +{ + if (dma_type == QAIF_AIF_IRQ) + return (v)->rddma_irq_reg_base + offset + + (v)->rddma_irq_stride * (v)->ee; + return (v)->codec_rddma_irq_reg_base + offset + + (v)->codec_rddma_irq_stride * (v)->ee; +} + +/* RDDMA Period Interrupts */ +#define QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x00) +#define QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x08) +#define QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x10) +#define QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x18) +#define QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x20) +/* RDDMA Underflow Interrupts */ +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x28) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x30) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x38) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x40) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x48) +/* RDDMA Error Response Interrupts */ +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x50) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x58) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x60) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x68) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x70) + +static inline u32 QAIF_EE_WRDMA_IRQ_REG_ADDR(const struct qaif_variant *v, + enum qaif_irq_type_t dma_type, + u32 offset) +{ + if (dma_type == QAIF_AIF_IRQ) + return (v)->wrdma_irq_reg_base + offset + + (v)->wrdma_irq_stride * (v)->ee; + return (v)->codec_wrdma_irq_reg_base + offset + + (v)->codec_wrdma_irq_stride * (v)->ee; +} + +/* WRDMA Period Interrupts */ +#define QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x00) +#define QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x08) +#define QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x10) +#define QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x18) +#define QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x20) +/* WRDMA Overflow Interrupts */ +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x28) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x30) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x38) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x40) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x48) +/* WRDMA Error Response Interrupts */ +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x50) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x58) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x60) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x68) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x70) + +static inline u32 QAIF_DMACFG_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CFG_REG(v, chan); + return QAIF_CODEC_WRDMA_CFG_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CFG_REG(v, chan); + return QAIF_WRDMA_CFG_REG(v, chan); +} + +static inline u32 QAIF_DMACTL_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CTL_REG(v, chan); + return QAIF_CODEC_WRDMA_CTL_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CTL_REG(v, chan); + return QAIF_WRDMA_CTL_REG(v, chan); +} + +static inline u32 QAIF_DMABUFF_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, chan); + return QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_BUFF_LEN_REG(v, chan); + return QAIF_WRDMA_BUFF_LEN_REG(v, chan); +} + +static inline u32 QAIF_DMACURR_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, chan); + return QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CURR_ADDR_REG(v, chan); + return QAIF_WRDMA_CURR_ADDR_REG(v, chan); +} + +static inline u32 QAIF_DMAPER_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, chan); + return QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_PERIOD_CNT_REG(v, chan); + return QAIF_WRDMA_PERIOD_CNT_REG(v, chan); +} + +static inline u32 QAIF_DMAPER_LEN_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, chan); + return QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_PERIOD_LEN_REG(v, chan); + return QAIF_WRDMA_PERIOD_LEN_REG(v, chan); +} + +static inline u32 QAIF_DMABASE_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, chan); + return QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_BASE_ADDR_REG(v, chan); + return QAIF_WRDMA_BASE_ADDR_REG(v, chan); +} + +static inline u32 QAIF_SID_MAP_REG(int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_SID_MAP_REG; + return QAIF_CODEC_WRDMA_SID_MAP_REG; + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_SID_MAP_REG; + return QAIF_WRDMA_SID_MAP_REG; +} + +#endif /* __QAIF_REG_H__ */ diff --git a/sound/soc/qcom/qaif.h b/sound/soc/qcom/qaif.h new file mode 100644 index 0000000000000..f52c92289813f --- /dev/null +++ b/sound/soc/qcom/qaif.h @@ -0,0 +1,576 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011,2013-2015,2020 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif.h -- ALSA SoC CPU-Platform DAI driver header file for QTi QAIF + */ +#ifndef __QAIF_H__ +#define __QAIF_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MI2S_SEPTENARY 35 + +#define SMMU_SID_OFFSET 32 +#define LPASS_MAX_MI2S_PORTS (8) +#define LPASS_MAX_AIF_DMA_IDX (8) +#define LPASS_MAX_CIF_DMA_IDX (8) +#define QAIF_CIF_DMA_INTF_ONE_CHANNEL (0x01) +#define QAIF_CIF_DMA_INTF_TWO_CHANNEL (0x03) +#define QAIF_CIF_DMA_INTF_FOUR_CHANNEL (0x0F) +#define QAIF_CIF_DMA_INTF_SIX_CHANNEL (0x3F) +#define QAIF_CIF_DMA_INTF_EIGHT_CHANNEL (0xFF) + +#define QAIF_DMACTL_ENABLE_ON 1 +#define QAIF_DMACTL_ENABLE_OFF 0 + +#define QAIF_DMACTL_DYNCLK_ON 1 +#define QAIF_DMACTL_DYNCLK_OFF 0 + +#define QAIF_MAX_AIF_CFG_CNT (LPASS_MAX_AIF_DMA_IDX / 2) + +/* TODO: confirm if only dma0...3 are active. */ +#define QAIF_IRQ_DMA_ALL (0xf) + +/* Individual bit masks (hex) */ +#define QAIF_AUD_INTF_CTL_ENABLE 0x00000001 /* bit 0 ENABLE RX and TX*/ +#define QAIF_AUD_INTF_CTL_ENABLE_TX 0x00000010 /* bit 4 */ +#define QAIF_AUD_INTF_CTL_ENABLE_RX 0x00000100 /* bit 8 */ +#define QAIF_AUD_INTF_CTL_RESET 0x00001000 /* bit 12 RESET RX and TX*/ +#define QAIF_AUD_INTF_CTL_RESET_TX 0x00010000 /* bit 16 */ +#define QAIF_AUD_INTF_CTL_RESET_RX 0x00100000 /* bit 20 */ + +/* Combined masks */ +#define QAIF_AUD_INTF_CTL_ENABLE_ALL 0x00000110 /* bits 4,8 */ +#define QAIF_AUD_INTF_CTL_RESET_ALL 0x00110000 /* bits 16,20 */ + +#define QAIF_AUD_INTF_CTL_MONO 1 /* Mono Mode True */ +#define QAIF_AUD_INTF_CTL_STEREO 0 /* Mono Mode False */ + +#define QAIF_AIF_SAMPLE_WIDTH(bits) ((bits) - 1) +#define QAIF_AIF_SLOT_WIDTH(bits) ((bits) - 1) + +#define QAIF_DMA_CLK_RATE_HZ 153600000 + +#define QAIF_DMACTL_WM_5 4 +#define QAIF_DMACTL_WM_8 7 +#define QAIF_DMACTL_BURSTEN 1 + +#define QAIF_MAX_LANES 8 + +/* QAIF_AUD_INTF_SYNC_CFG_REG bit masks and shifts */ +#define QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_MASK BIT(12) +#define QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_SHFT 12 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_MASK GENMASK(9, 8) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_SHFT 8 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_MASK GENMASK(5, 4) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_SHFT 4 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_MASK BIT(0) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_SHFT 0 + +/* QAIF_AUD_INTF_LANE_CFG_REG bit masks and shifts */ +#define QAIF_AUD_INTF_LANE_CFG_LOOPBACK_MASK BIT(31) +#define QAIF_AUD_INTF_LANE_CFG_LOOPBACK_SHFT 31 + +#define QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_MASK BIT(16) +#define QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_SHFT 16 + +#define QAIF_AUD_INTF_LANE_CFG_LANE_EN_MASK GENMASK(15, 8) +#define QAIF_AUD_INTF_LANE_CFG_LANE_EN_SHFT 8 + +#define QAIF_AUD_INTF_LANE_CFG_LANE_DIR_MASK GENMASK(7, 0) +#define QAIF_AUD_INTF_LANE_CFG_LANE_DIR_SHFT 0 + +/* ========== QAIF_AUD_INTF_BIT_WIDTH_CFG_REG bit masks and shifts ========== */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK GENMASK(28, 24) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_SHFT 24 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK GENMASK(20, 16) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_SHFT 16 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK GENMASK(12, 8) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_SHFT 8 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK GENMASK(4, 0) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_SHFT 0 + +/* ========== QAIF_AUD_INTF_BIT_WIDTH_CFG_REG - Combined masks for RMW ========== */ +/* RX-only fields mask (for preserving TX fields) */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_RX_FIELDS_MASK \ + (QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK | \ + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK) + +/* TX-only fields mask (for preserving RX fields) */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_TX_FIELDS_MASK \ + (QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK | \ + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK) + +/* ========== QAIF_AUD_INTF_MI2S_CFG_REG bit masks and shifts ========== */ +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK BIT(1) +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT 1 + +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK BIT(0) +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT 0 + +/* Combined masks for Read-Modify-Write operations */ +#define QAIF_AUD_INTF_MI2S_CFG_RX_FIELDS_MASK \ + (QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK) + +#define QAIF_AUD_INTF_MI2S_CFG_TX_FIELDS_MASK \ + (QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK) + +enum qxm_sel { + QXM0 = 0, + QXM1 = 1, + MAX_QXM_TYPE, +}; + +/* Enum list to define the interface direction */ +enum aud_dma_util_direction { + AUD_DMA_SINK = 0, + AUD_DMA_SOURCE = 1, +}; + +static inline bool is_cif_dma_port(int dai_id) +{ + switch (dai_id) { + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + return true; + } + return false; +} + +/* Enum list to define the list of HW interfaces DMA Util is used for + * example, Display port can be part of the below list in future + */ +enum qaif_type_t { + QAIF_INVALID = -1, + QAIF = 0, + QAIF_VA, + QAIF_MAX_TYPES +}; + +enum qaif_irq_type_t { + QAIF_AIF_IRQ = 0, + QAIF_CIF_IRQ = 1, + QAIF_AUD_INTF_IRQ = 2, + QAIF_IRQ_MAX = 3 +}; + +enum qaif_dma_type { + QAIF_AIF_DMA = 0, + QAIF_CIF_DMA = 1, + DMA_TYPE_MAX +}; + +struct qaif_dmactl { + //AUDIO_CORE_QAIF_CODEC_xDMAa_CTL + struct regmap_field *enable; + struct regmap_field *reset; + + //AUDIO_CORE_QAIF_CODEC_xDMAa_CFG + struct regmap_field *num_ot; //outstanding transaction + struct regmap_field *dma_dyncclk; + struct regmap_field *burst16; + struct regmap_field *burst8; + struct regmap_field *burst4; + struct regmap_field *burst2; + struct regmap_field *burst1; + struct regmap_field *shram_wm; //SHRAM_WATERMRK + +}; + +struct qaif_cdc_intfctl { + //AUDIO_CORE_QAIF_CODEC_xDMAa_INTF_CFG + struct regmap_field *active_ch_en; + struct regmap_field *fs_sel; + struct regmap_field *fs_delay; + struct regmap_field *fs_out_gate; + struct regmap_field *intf_dyncclk; + struct regmap_field *en_16bit_unpack; +}; + +struct qaif_aud_intfctl { + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG */ + struct regmap_field *inv_sync; /* qcom,qaif-aif-invert-sync */ + struct regmap_field *sync_delay; /* qcom,qaif-aif-sync-delay */ + struct regmap_field *sync_mode; /* qcom,qaif-aif-sync-mode */ + struct regmap_field *sync_src; /* qcom,qaif-aif-sync-src */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG */ + struct regmap_field *slot_width_rx; /* qcom,qaif-aif-slot-width-rx (MIC/RX Path) */ + struct regmap_field *slot_width_tx; /* qcom,qaif-aif-slot-width-tx (SPKR/TX Path) */ + struct regmap_field *sample_width_rx; /* qcom,qaif-aif-sample-width-rx (MIC/RX Path) */ + struct regmap_field *sample_width_tx; /* qcom,qaif-aif-sample-width-tx (SPKR/TX Path) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG */ + struct regmap_field *mono_mode_rx; /* qcom,qaif-aif-mono-mode-rx (SPKR/TX Path) */ + struct regmap_field *mono_mode_tx; /* qcom,qaif-aif-mono-mode-tx (MIC/RX Path) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG */ + struct regmap_field *lane_en; /* Lane enable mask (bits 8-15) */ + struct regmap_field *lane_dir; /* Lane direction mask (bits 0-7, 0=TX, 1=RX) */ + struct regmap_field *loopback_en; /* qcom,qaif-aif-loopback-en (bit 31) */ + struct regmap_field *ctrl_data_oe; /* qcom,qaif-aif-ctrl-data-oe (bit 16) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX */ + struct regmap_field *slot_en_rx_mask; /* qcom,qaif-aif-slot-en-rx-mask (32-bit mask) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX */ + struct regmap_field *slot_en_tx_mask; /* qcom,qaif-aif-slot-en-tx-mask (32-bit mask) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG */ + struct regmap_field *full_cycle_en; /* qcom,qaif-aif-full-cycle-en */ + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG */ + struct regmap_field *bits_per_lane; /* qcom,qaif-aif-bits-per-lane */ +}; + +/* Lane configuration structure */ +struct qaif_lane_config { + u32 enable; /* 1 = enabled, 0 = disabled */ + u32 direction; /* 0 = TX_SPKR, 1 = RX_MIC */ +}; + +/* QAIF Audio Interface Configuration Structure */ +struct qaif_aif_config { + /* Sync configuration */ + u32 sync_mode; /* qcom,qaif-aif-sync-mode */ + u32 sync_src; /* qcom,qaif-aif-sync-src */ + u32 invert_sync; /* qcom,qaif-aif-invert-sync */ + u32 sync_delay; /* qcom,qaif-aif-sync-delay */ + /* Slot and sample width configuration */ + u32 slot_width_rx; /* qcom,qaif-aif-slot-width-rx (MIC/RX Path) */ + u32 slot_width_tx; /* qcom,qaif-aif-slot-width-tx (SPKR/TX Path) */ + u32 sample_width_rx; /* qcom,qaif-aif-sample-width-rx (MIC/RX Path) */ + u32 sample_width_tx; /* qcom,qaif-aif-sample-width-tx (SPKR/TX Path) */ + /* Slot enable masks (32-bit masks for 32 slots) */ + u32 slot_en_rx_mask; /* qcom,qaif-aif-slot-en-rx-mask (MIC/RX Path) */ + u32 slot_en_tx_mask; /* qcom,qaif-aif-slot-en-tx-mask (SPKR/TX Path) */ + /* Control configuration */ + u32 loopback_en; /* qcom,qaif-aif-loopback-en */ + u32 ctrl_data_oe; /* qcom,qaif-aif-ctrl-data-oe */ + /* Lane configuration */ + u32 num_lanes; /* Number of lanes configured */ + struct qaif_lane_config lane_cfg[QAIF_MAX_LANES]; /* qcom,qaif-aif-lane-config */ + u32 lane_en_mask; + u32 lane_dir_mask; + /* Mono/Stereo mode */ + u32 mono_mode_tx; /* qcom,qaif-aif-mono-mode-tx (MIC/RX Path) */ + u32 mono_mode_rx; /* qcom,qaif-aif-mono-mode-rx (SPKR/TX Path) */ + /* Frame configuration */ + u32 full_cycle_en; /* qcom,qaif-aif-full-cycle-en */ + u32 bits_per_lane; /* qcom,qaif-aif-bits-per-lane (FRAME_CFG) */ +}; + +struct qaif_pcm_data { + int stream_dma_idx; + //int i2s_port; +}; + +struct qaif_dma_mem_info { + dma_addr_t dma_addr; + size_t alloc_size; + void *vaddr; +}; + +struct qaif_dmaidx_dai_map { + unsigned int dai_id; +}; + +/* Both the CPU DAI and platform drivers will access this data */ +struct qaif_drv_data { + /* MI2S system clock */ + struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS]; + + /* MI2S bit clock (derived from system clock by a divider */ + struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; + + /* The state of MI2S prepare dai_ops was called */ + bool mi2s_was_prepared[LPASS_MAX_MI2S_PORTS]; + + /* SOC specific clock list */ + struct clk_bulk_data *clks; + int num_clks; + + struct clk *aud_dma_clk; + struct clk *aud_dma_mem_clk; + + /* Qualcomm audio interface (QAIF) registers */ + void __iomem *audio_qaif; + + /* regmap backed by the Qualcomm audio interface (QAIF) registers */ + struct regmap *audio_qaif_map; + + /* interrupts from the Qualcomm audio interface (QAIF) */ + int audio_qaif_irq; + + /* QAIF init config refcount*/ + unsigned int qaif_init_ref_cnt; + + /* SOC specific variations in the QAIF IP integration */ + struct qaif_variant *variant; + + /* bit map to keep track of dma idx allocations */ + unsigned long aif_dma_idx_bit_map; + unsigned long cif_dma_idx_bit_map; + + /* used it for handling interrupt per dma channel */ + struct snd_pcm_substream *aif_substream[LPASS_MAX_AIF_DMA_IDX]; + struct snd_pcm_substream *cif_substream[LPASS_MAX_CIF_DMA_IDX]; + + u64 smmu_csid_bits; + u64 smmu_sid_bits; + + /* DMA Heap handle*/ + struct dma_heap *dma_heap; + /* DMA Heap name*/ + const char *dma_heap_name; + /* DMA info handle per stream/dma idx*/ + struct qaif_dma_mem_info *aif_dma_heap[LPASS_MAX_AIF_DMA_IDX]; + struct qaif_dma_mem_info *cif_dma_heap[LPASS_MAX_CIF_DMA_IDX]; + +}; + +enum qaif_summary_irq_bitmask { + QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA = BIT(0), + QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA = BIT(1), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA = BIT(2), + QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA = BIT(3), + QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA = BIT(4), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA = BIT(5), + + QAIF_SUMMARY_BITMASK_AUD_OVERFLOW = BIT(6), + QAIF_SUMMARY_BITMASK_AUD_UNDERFLOW = BIT(7), + + QAIF_SUMMARY_BITMASK_RATE_DET = BIT(8), + QAIF_SUMMARY_BITMASK_VFR = BIT(9), + QAIF_SUMMARY_BITMASK_GRP = BIT(10), + QAIF_SUMMARY_BITMASK_RDDMA_OVERLAP = BIT(11), + QAIF_SUMMARY_BITMASK_WRDMA_OVERLAP = BIT(12), + QAIF_SUMMARY_BITMASK_INTF_OVERLAP = BIT(13), + QAIF_SUMMARY_BITMASK_GRP_OVERLAP = BIT(14), + + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_RDDMA = BIT(15), + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_WRDMA = BIT(17), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA = BIT(18), + QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA = BIT(19), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP = BIT(20), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA = BIT(24), + QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA = BIT(25), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA = BIT(26) + +}; + +/* defines the bitmask in the status register for each of the clients */ +enum qaif_client_status_register_bitmask_info { + QAIF_BITMASK_GROUP_INF = 0x400, + QAIF_BITMASK_AIF_RDDMA_WRDMA = 0x3F, + QAIF_BITMASK_CIF_RDDMA_WRDMA = 0x71c0000, + QAIF_BITMASK_DP_RDDMA = 0xe00000, + QAIF_BITMASK_AUD_INF = 0xC0, +}; + +struct qaif_irq_map { + int client_id; + u32 mask; + irqreturn_t (*client_irq_handler)(struct qaif_drv_data *drvdata, u32 irq_status); +}; + +enum dma_type { + DMA_TYPE_RDDMA, + DMA_TYPE_WRDMA +}; + +enum qaif_irq { + QAIF_IRQ_PERIOD, + QAIF_IRQ_OVERFLOW, + QAIF_IRQ_UNDERFLOW, + QAIF_IRQ_ERROR +}; + +/* list of clients for IRQ Util */ +enum qaif_client_info { + QAIF_CLIENT_ID_GROUP_INF = 0, + QAIF_CLIENT_ID_AIF_DMA = 1, + QAIF_CLIENT_ID_CIF_DMA = 2, + QAIF_CLIENT_ID_DP_DMA = 3, + QAIF_CLIENT_ID_AUD_INF = 4, + QAIF_CLIENT_ID_MAX +}; + +struct qaif_variant { + u32 ee; + u32 qaif_type; + + u32 num_rddma; + u32 num_wrdma; + u32 wrdma_start; + + u32 num_codec_rddma; //RX + u32 num_codec_wrdma; //TX + u32 codec_wrdma_start; + u32 num_intf; + + u32 rddma_reg_base; + u32 rddma_stride; + u32 codec_rddma_reg_base; + u32 codec_rddma_stride; + + u32 wrdma_reg_base; + u32 wrdma_stride; + u32 codec_wrdma_reg_base; + u32 codec_wrdma_stride; + + u32 rddma_irq_reg_base; + u32 rddma_irq_stride; + u32 codec_rddma_irq_reg_base; + u32 codec_rddma_irq_stride; + + u32 wrdma_irq_reg_base; + u32 wrdma_irq_stride; + u32 codec_wrdma_irq_reg_base; + u32 codec_wrdma_irq_stride; + + u32 qxm_type; + u32 rd_len; + u32 rddma_shram_len; + u32 rddma_shram_start_addr[DMA_TYPE_MAX]; + u32 wr_len; + u32 wrdma_shram_len; + u32 wrdma_shram_start_addr[DMA_TYPE_MAX]; + + /* AIF RDDMA register fields */ + const struct reg_field rddma_enable; + const struct reg_field rddma_reset; + const struct reg_field rddma_num_ot; + const struct reg_field rddma_dma_dyncclk; + const struct reg_field rddma_burst16; + const struct reg_field rddma_burst8; + const struct reg_field rddma_burst4; + const struct reg_field rddma_burst2; + const struct reg_field rddma_burst1; + const struct reg_field rddma_shram_wm; + + /* AIF WRDMA register fields */ + const struct reg_field wrdma_enable; + const struct reg_field wrdma_reset; + const struct reg_field wrdma_num_ot; + const struct reg_field wrdma_dma_dyncclk; + const struct reg_field wrdma_burst16; + const struct reg_field wrdma_burst8; + const struct reg_field wrdma_burst4; + const struct reg_field wrdma_burst2; + const struct reg_field wrdma_burst1; + const struct reg_field wrdma_shram_wm; + + /* CODEC RDDMA register fields */ + const struct reg_field cif_rddma_enable; + const struct reg_field cif_rddma_reset; + const struct reg_field cif_rddma_num_ot; + const struct reg_field cif_rddma_dma_dyncclk; + const struct reg_field cif_rddma_burst16; + const struct reg_field cif_rddma_burst8; + const struct reg_field cif_rddma_burst4; + const struct reg_field cif_rddma_burst2; + const struct reg_field cif_rddma_burst1; + const struct reg_field cif_rddma_shram_wm; + const struct reg_field cif_rddma_active_ch_en; + const struct reg_field cif_rddma_fs_sel; + const struct reg_field cif_rddma_fs_delay; + const struct reg_field cif_rddma_fs_out_gate; + const struct reg_field cif_rddma_intf_dyncclk; + const struct reg_field cif_rddma_en_16bit_unpack; + + /* CODEC WRDMA register fields */ + const struct reg_field cif_wrdma_enable; + const struct reg_field cif_wrdma_reset; + const struct reg_field cif_wrdma_num_ot; + const struct reg_field cif_wrdma_dma_dyncclk; + const struct reg_field cif_wrdma_burst16; + const struct reg_field cif_wrdma_burst8; + const struct reg_field cif_wrdma_burst4; + const struct reg_field cif_wrdma_burst2; + const struct reg_field cif_wrdma_burst1; + const struct reg_field cif_wrdma_shram_wm; + const struct reg_field cif_wrdma_active_ch_en; + const struct reg_field cif_wrdma_fs_sel; + const struct reg_field cif_wrdma_fs_delay; + const struct reg_field cif_wrdma_fs_out_gate; + const struct reg_field cif_wrdma_intf_dyncclk; + const struct reg_field cif_wrdma_en_16bit_unpack; + + /* Regmap fields of AIF interface registers bitfields */ + const struct reg_field aif_inv_sync; + const struct reg_field aif_sync_delay; + const struct reg_field aif_sync_mode; + const struct reg_field aif_sync_src; + const struct reg_field aif_sample_width_rx; + const struct reg_field aif_sample_width_tx; + const struct reg_field aif_slot_width_rx; + const struct reg_field aif_slot_width_tx; + const struct reg_field aif_bits_per_lane; + const struct reg_field aif_slot_en_tx_mask; + const struct reg_field aif_slot_en_rx_mask; + const struct reg_field aif_loopback_en; + const struct reg_field aif_ctrl_data_oe; + const struct reg_field aif_lane_en; + const struct reg_field aif_lane_dir; + const struct reg_field aif_mono_mode_rx; + const struct reg_field aif_mono_mode_tx; + const struct reg_field aif_full_cycle_en; + + /* Regmap fields of DMACTL registers bitfields */ + struct qaif_dmactl *aif_rd_dmactl; + struct qaif_dmactl *aif_wr_dmactl; + + /* Regmap fields of CODEC DMA CTRL registers */ + struct qaif_dmactl *cif_rd_dmactl; + struct qaif_dmactl *cif_wr_dmactl; + + struct qaif_aif_config aif_intf_cfg[QAIF_MAX_AIF_CFG_CNT]; + struct qaif_aud_intfctl *aif_intfctl; + + struct qaif_cdc_intfctl *cif_rddma_intfctl; + struct qaif_cdc_intfctl *cif_wrdma_intfctl; + + /* Platform-specific data */ + const char **clk_name; + int num_clks; + struct snd_soc_dai_driver *dai_driver; + int num_dai; + const char **dai_osr_clk_names; + const char **dai_bit_clk_names; + + /* Platform-specific function pointers */ + int (*init)(struct platform_device *pdev); + int (*exit)(struct platform_device *pdev); + int (*alloc_stream_dma_idx)(struct qaif_drv_data *data, int direction, unsigned int dai_id); + int (*free_stream_dma_idx)(struct qaif_drv_data *data, int chan, unsigned int dai_id); + int (*get_dma_idx)(unsigned int dai_id); + +}; + +/* External DAI ops structures defined in qaif-cpu.c */ +extern const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops; +extern const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops; + +/* Platform driver functions defined in qaif-cpu.c */ +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev); +int asoc_qcom_qaif_platform_register(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev); + +#endif /* __QAIF_H__ */ From 16161e52de3143b3ad12aa7c78501a32dd14fefa Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Fri, 29 May 2026 11:44:54 +0530 Subject: [PATCH 0994/1058] ASoC: qcom: Add QAIF CPU DAI driver Add the CPU DAI driver for the Qualcomm Technologies Qualcomm Audio Interface (QAIF). Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/qaif-cpu.c | 1585 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1585 insertions(+) create mode 100644 sound/soc/qcom/qaif-cpu.c diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c new file mode 100644 index 0000000000000..0a3bd9e5879a0 --- /dev/null +++ b/sound/soc/qcom/qaif-cpu.c @@ -0,0 +1,1585 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-cpu.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" + +#define QAIF_AIF_REG_READ 1 +#define QAIF_AIF_REG_WRITE 0 + +static int qaif_cif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + struct qaif_cdc_intfctl *rd_intfctl; + struct qaif_cdc_intfctl *wr_intfctl; + + /* Allocate RDDMA control structure */ + rd_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + /* Allocate WRDMA control structure */ + wr_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + /* Allocate RDDMA INTF control structure */ + rd_intfctl = devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KERNEL); + if (!rd_intfctl) + return -ENOMEM; + + /* Allocate WRDMA INTF control structure */ + wr_intfctl = devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KERNEL); + if (!wr_intfctl) + return -ENOMEM; + + /* =================================================================== + * Allocate RDDMA (RX/Playback) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->cif_rddma_enable); + rd_dmactl->reset = devm_regmap_field_alloc(dev, map, v->cif_rddma_reset); + + /* CFG register fields */ + rd_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->cif_rddma_shram_wm); + rd_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst1); + rd_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst2); + rd_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst4); + rd_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst8); + rd_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst16); + rd_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_rddma_dma_dyncclk); + rd_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->cif_rddma_num_ot); + + /* INTF_CFG register fields */ + rd_intfctl->en_16bit_unpack = + devm_regmap_field_alloc(dev, map, v->cif_rddma_en_16bit_unpack); + rd_intfctl->intf_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_rddma_intf_dyncclk); + rd_intfctl->fs_out_gate = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_out_gate); + rd_intfctl->fs_sel = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_sel); + rd_intfctl->fs_delay = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_delay); + rd_intfctl->active_ch_en = devm_regmap_field_alloc(dev, map, v->cif_rddma_active_ch_en); + + /* =================================================================== + * Allocate WRDMA (TX/Capture) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->cif_wrdma_enable); + wr_dmactl->reset = devm_regmap_field_alloc(dev, map, v->cif_wrdma_reset); + + /* CFG register fields */ + wr_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->cif_wrdma_shram_wm); + wr_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst1); + wr_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst2); + wr_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst4); + wr_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst8); + wr_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst16); + wr_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_wrdma_dma_dyncclk); + wr_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->cif_wrdma_num_ot); + + /* INTF_CFG register fields */ + wr_intfctl->en_16bit_unpack = + devm_regmap_field_alloc(dev, map, v->cif_wrdma_en_16bit_unpack); + wr_intfctl->intf_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_wrdma_intf_dyncclk); + wr_intfctl->fs_out_gate = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_out_gate); + wr_intfctl->fs_sel = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_sel); + wr_intfctl->fs_delay = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_delay); + wr_intfctl->active_ch_en = devm_regmap_field_alloc(dev, map, v->cif_wrdma_active_ch_en); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(rd_dmactl->enable) || IS_ERR(wr_dmactl->enable) || + IS_ERR(rd_dmactl->reset) || IS_ERR(wr_dmactl->reset) || + IS_ERR(rd_dmactl->num_ot) || IS_ERR(wr_dmactl->num_ot) || + IS_ERR(rd_dmactl->dma_dyncclk) || IS_ERR(wr_dmactl->dma_dyncclk) || + IS_ERR(rd_dmactl->burst16) || IS_ERR(wr_dmactl->burst16) || + IS_ERR(rd_dmactl->burst8) || IS_ERR(wr_dmactl->burst8) || + IS_ERR(rd_dmactl->burst4) || IS_ERR(wr_dmactl->burst4) || + IS_ERR(rd_dmactl->burst2) || IS_ERR(wr_dmactl->burst2) || + IS_ERR(rd_dmactl->burst1) || IS_ERR(wr_dmactl->burst1) || + IS_ERR(rd_dmactl->shram_wm) || IS_ERR(wr_dmactl->shram_wm) || + IS_ERR(rd_intfctl->active_ch_en) || IS_ERR(wr_intfctl->active_ch_en) || + IS_ERR(rd_intfctl->fs_sel) || IS_ERR(wr_intfctl->fs_sel) || + IS_ERR(rd_intfctl->fs_delay) || IS_ERR(wr_intfctl->fs_delay) || + IS_ERR(rd_intfctl->fs_out_gate) || IS_ERR(wr_intfctl->fs_out_gate) || + IS_ERR(rd_intfctl->intf_dyncclk) || IS_ERR(wr_intfctl->intf_dyncclk) || + IS_ERR(rd_intfctl->en_16bit_unpack) || IS_ERR(wr_intfctl->en_16bit_unpack)) { + dev_err(dev, "error allocating codec dma regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->cif_rd_dmactl = rd_dmactl; + v->cif_wr_dmactl = wr_dmactl; + v->cif_rddma_intfctl = rd_intfctl; + v->cif_wrdma_intfctl = wr_intfctl; + + return 0; +} + +static struct qaif_cdc_intfctl * +qaif_get_cif_intfctl_handle(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + unsigned int dai_id = cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl = NULL; + + if (!v) { + dev_err(soc_runtime->dev, "No variant data\n"); + return intfctl; + } + + switch (dai_id) { + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + intfctl = v->cif_rddma_intfctl; + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + intfctl = v->cif_wrdma_intfctl; + break; + default: + dev_err(soc_runtime->dev, "invalid dai id for dma ctl: %d\n", dai_id); + break; + } + return intfctl; +} + +static int qaif_cif_daiops_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + struct qaif_cdc_intfctl *intfctl = NULL; + unsigned int dai_id = cpu_dai->driver->id; + unsigned int ret, regval; + unsigned int channels = params_channels(params); + int idx; + + pr_err("%s:%d: dai_id=%u stream=%d channels=%u rate=%u\n", + __func__, __LINE__, dai_id, substream->stream, channels, + params_rate(params)); + + switch (channels) { + case 1: + regval = QAIF_CIF_DMA_INTF_ONE_CHANNEL; + break; + case 2: + regval = QAIF_CIF_DMA_INTF_TWO_CHANNEL; + break; + case 4: + regval = QAIF_CIF_DMA_INTF_FOUR_CHANNEL; + break; + case 6: + regval = QAIF_CIF_DMA_INTF_SIX_CHANNEL; + break; + case 8: + regval = QAIF_CIF_DMA_INTF_EIGHT_CHANNEL; + break; + default: + dev_err(soc_runtime->dev, "invalid PCM config\n"); + return -EINVAL; + } + + intfctl = qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx = v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + //active channel mask + ret = regmap_fields_write(intfctl->active_ch_en, idx, regval); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to intfctl active_ch_en reg field: %d\n", ret); + return ret; + } + pr_err("%s:%d: configured active_ch_en idx=%d val=0x%x\n", + __func__, __LINE__, idx, regval); + + return 0; +} + +static int qaif_cif_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + unsigned int dai_id = cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl = NULL; + int ret = 0, idx; + + pr_err("%s:%d: dai_id=%u stream=%d cmd=%d\n", + __func__, __LINE__, dai_id, substream->stream, cmd); + + intfctl = qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx = v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = regmap_fields_write(intfctl->intf_dyncclk, idx, 1); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl intf_dyncclk reg field: %d\n", + ret); + return ret; + } + /* ToDo: Hardcoded for now, Later to modify dynamically */ + ret = regmap_fields_write(intfctl->fs_sel, idx, 0x0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl codec_fs_sel reg field: %d\n", + ret); + return ret; + } + + ret = regmap_fields_write(intfctl->en_16bit_unpack, idx, 0x1); + /* ToDo: based on bw and packing enable flag */ + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl en_16bit_unpack reg field: %d\n", + ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = regmap_fields_write(intfctl->intf_dyncclk, idx, 0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl intf_dyncclk reg field: %d\n", + ret); + return ret; + } + ret = regmap_fields_write(intfctl->en_16bit_unpack, idx, 0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl en_16bit_unpack reg field: %d\n", + ret); + return ret; + } + break; + default: + ret = -EINVAL; + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, cmd); + break; + } + pr_err("%s:%d: cmd=%d ret=%d idx=%d\n", + __func__, __LINE__, cmd, ret, idx); + return ret; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops = { + .hw_params = qaif_cif_daiops_hw_params, + .trigger = qaif_cif_daiops_trigger, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cif_dai_ops); + +static int qaif_aif_cfg_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_aud_intfctl *aif_intfctl; + + /* Allocate AIF interface control structure */ + aif_intfctl = devm_kzalloc(dev, sizeof(struct qaif_aud_intfctl), GFP_KERNEL); + if (!aif_intfctl) + return -ENOMEM; + + /* =================================================================== + * Allocate regmap fields for AUD_INTF SYNC_CFG register + * =================================================================== + */ + aif_intfctl->inv_sync = devm_regmap_field_alloc(dev, map, v->aif_inv_sync); + aif_intfctl->sync_delay = devm_regmap_field_alloc(dev, map, v->aif_sync_delay); + aif_intfctl->sync_mode = devm_regmap_field_alloc(dev, map, v->aif_sync_mode); + aif_intfctl->sync_src = devm_regmap_field_alloc(dev, map, v->aif_sync_src); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF BIT_WIDTH_CFG register + * =================================================================== + */ + aif_intfctl->slot_width_rx = devm_regmap_field_alloc(dev, map, v->aif_slot_width_rx); + aif_intfctl->slot_width_tx = devm_regmap_field_alloc(dev, map, v->aif_slot_width_tx); + aif_intfctl->sample_width_rx = devm_regmap_field_alloc(dev, map, v->aif_sample_width_rx); + aif_intfctl->sample_width_tx = devm_regmap_field_alloc(dev, map, v->aif_sample_width_tx); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF MI2S_CFG register + * =================================================================== + */ + aif_intfctl->mono_mode_rx = devm_regmap_field_alloc(dev, map, v->aif_mono_mode_rx); + aif_intfctl->mono_mode_tx = devm_regmap_field_alloc(dev, map, v->aif_mono_mode_tx); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF LANE_CFG register + * =================================================================== + */ + aif_intfctl->lane_en = devm_regmap_field_alloc(dev, map, v->aif_lane_en); + aif_intfctl->lane_dir = devm_regmap_field_alloc(dev, map, v->aif_lane_dir); + aif_intfctl->loopback_en = devm_regmap_field_alloc(dev, map, v->aif_loopback_en); + aif_intfctl->ctrl_data_oe = devm_regmap_field_alloc(dev, map, v->aif_ctrl_data_oe); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF SLOT_EN registers + * =================================================================== + */ + aif_intfctl->slot_en_rx_mask = devm_regmap_field_alloc(dev, map, v->aif_slot_en_rx_mask); + aif_intfctl->slot_en_tx_mask = devm_regmap_field_alloc(dev, map, v->aif_slot_en_tx_mask); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF FRAME_CFG register + * =================================================================== + */ + aif_intfctl->bits_per_lane = devm_regmap_field_alloc(dev, map, v->aif_bits_per_lane); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF CFG register + * =================================================================== + */ + aif_intfctl->full_cycle_en = devm_regmap_field_alloc(dev, map, v->aif_full_cycle_en); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(aif_intfctl->inv_sync) || IS_ERR(aif_intfctl->sync_delay) || + IS_ERR(aif_intfctl->sync_mode) || IS_ERR(aif_intfctl->sync_src) || + IS_ERR(aif_intfctl->slot_width_rx) || IS_ERR(aif_intfctl->slot_width_tx) || + IS_ERR(aif_intfctl->sample_width_rx) || IS_ERR(aif_intfctl->sample_width_tx) || + IS_ERR(aif_intfctl->mono_mode_rx) || IS_ERR(aif_intfctl->mono_mode_tx) || + IS_ERR(aif_intfctl->lane_en) || IS_ERR(aif_intfctl->lane_dir) || + IS_ERR(aif_intfctl->loopback_en) || IS_ERR(aif_intfctl->ctrl_data_oe) || + IS_ERR(aif_intfctl->slot_en_rx_mask) || IS_ERR(aif_intfctl->slot_en_tx_mask) || + IS_ERR(aif_intfctl->bits_per_lane) || IS_ERR(aif_intfctl->full_cycle_en)) { + dev_err(dev, "error allocating AIF interface regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->aif_intfctl = aif_intfctl; + + dev_info(dev, "Successfully initialized AIF interface control bitfields\n"); + return 0; +} + +static int qaif_aif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + + /* Allocate RDDMA control structure */ + rd_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + /* Allocate WRDMA control structure */ + wr_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + /* =================================================================== + * Allocate RDDMA (RX/Playback) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->rddma_enable); + rd_dmactl->reset = devm_regmap_field_alloc(dev, map, v->rddma_reset); + + /* CFG register fields */ + rd_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->rddma_shram_wm); + rd_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->rddma_burst1); + rd_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->rddma_burst2); + rd_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->rddma_burst4); + rd_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->rddma_burst8); + rd_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->rddma_burst16); + rd_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->rddma_dma_dyncclk); + rd_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->rddma_num_ot); + + /* =================================================================== + * Allocate WRDMA (TX/Capture) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->wrdma_enable); + wr_dmactl->reset = devm_regmap_field_alloc(dev, map, v->wrdma_reset); + + /* CFG register fields */ + wr_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->wrdma_shram_wm); + wr_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->wrdma_burst1); + wr_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->wrdma_burst2); + wr_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->wrdma_burst4); + wr_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->wrdma_burst8); + wr_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->wrdma_burst16); + wr_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->wrdma_dma_dyncclk); + wr_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->wrdma_num_ot); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(rd_dmactl->enable) || IS_ERR(wr_dmactl->enable) || + IS_ERR(rd_dmactl->reset) || IS_ERR(wr_dmactl->reset) || + IS_ERR(rd_dmactl->num_ot) || IS_ERR(wr_dmactl->num_ot) || + IS_ERR(rd_dmactl->dma_dyncclk) || IS_ERR(wr_dmactl->dma_dyncclk) || + IS_ERR(rd_dmactl->burst16) || IS_ERR(wr_dmactl->burst16) || + IS_ERR(rd_dmactl->burst8) || IS_ERR(wr_dmactl->burst8) || + IS_ERR(rd_dmactl->burst4) || IS_ERR(wr_dmactl->burst4) || + IS_ERR(rd_dmactl->burst2) || IS_ERR(wr_dmactl->burst2) || + IS_ERR(rd_dmactl->burst1) || IS_ERR(wr_dmactl->burst1) || + IS_ERR(rd_dmactl->shram_wm) || IS_ERR(wr_dmactl->shram_wm)) { + dev_err(dev, "error allocating AIF dma regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->aif_rd_dmactl = rd_dmactl; + v->aif_wr_dmactl = wr_dmactl; + + return 0; +} + +static int qaif_aif_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx, ret = 0; + + pr_err("%s:%d: dai_id=%d stream=%d\n", + __func__, __LINE__, dai->driver->id, substream->stream); + + idx = v->get_dma_idx(dai->driver->id); + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = clk_prepare(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + pr_err("%s:%d: prepared bit_clk idx=%d\n", + __func__, __LINE__, idx); + return 0; +} + +static void qaif_aif_cpu_daiops_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx = v->get_dma_idx(dai->driver->id); + + pr_err("%s:%d: dai_id=%d stream=%d\n", + __func__, __LINE__, dai->driver->id, substream->stream); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + else + regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + + if (drvdata->mi2s_was_prepared[idx]) { + drvdata->mi2s_was_prepared[idx] = false; + clk_disable(drvdata->mi2s_bit_clk[idx]); + } + + clk_unprepare(drvdata->mi2s_bit_clk[idx]); +} + +static int qaif_aif_cpu_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx, ret = -EINVAL; + + idx = v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), QAIF_AUD_INTF_CTL_ENABLE_TX); + } else { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), QAIF_AUD_INTF_CTL_ENABLE_RX); + } + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + ret = clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + } else { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + } + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + clk_disable(drvdata->mi2s_bit_clk[idx]); + + break; + } + + return ret; +} + +static int qaif_aif_cpu_daiops_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_probe(struct snd_soc_dai *dai) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct qaif_variant *v = drvdata->variant; + unsigned int idx; + struct qaif_aif_config *aif_intf_cfg = NULL; + snd_pcm_format_t format = params_format(params); + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + unsigned int slot_width = 32; + int bitwidth, ret; + u32 sync_cfg_val, lane_cfg_val, mi2s_cfg_val, frame_cfg_val; + u32 tx_bw_fields, rx_bw_fields, bit_width_cfg_val; + + idx = v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + aif_intf_cfg = &v->aif_intf_cfg[idx]; + + if (!aif_intf_cfg) { + dev_err(dai->dev, "AIF interface config not found\n"); + return -EINVAL; + } + bitwidth = snd_pcm_format_width(format); + if (bitwidth < 0) { + dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); + return bitwidth; + } + + /* Combine all fields into single value */ + sync_cfg_val = ((aif_intf_cfg->invert_sync << QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_MASK) | + ((aif_intf_cfg->sync_delay << + QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_MASK) | + ((aif_intf_cfg->sync_mode << + QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_MASK) | + ((aif_intf_cfg->sync_src << QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_MASK); + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_SYNC_CFG_REG(idx), sync_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_SYNC_CFG_REG: %d\n", ret); + return ret; + } + + lane_cfg_val = ((aif_intf_cfg->loopback_en << QAIF_AUD_INTF_LANE_CFG_LOOPBACK_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LOOPBACK_MASK) | + ((aif_intf_cfg->ctrl_data_oe << + QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_SHFT) & + QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_MASK) | + ((aif_intf_cfg->lane_en_mask << + QAIF_AUD_INTF_LANE_CFG_LANE_EN_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LANE_EN_MASK) | + ((aif_intf_cfg->lane_dir_mask << + QAIF_AUD_INTF_LANE_CFG_LANE_DIR_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LANE_DIR_MASK); + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_LANE_CFG_REG(idx), lane_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_LANE_CFG_REG: %d\n", ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CFG_REG(idx), aif_intf_cfg->full_cycle_en); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_CFG_REG: %d\n", ret); + return ret; + } + dev_dbg(dai->dev, "%s: sync_cfg_val: %x, lane_cfg_val: %x, full_cycle_en: %x\n", + __func__, sync_cfg_val, lane_cfg_val, aif_intf_cfg->full_cycle_en); + + ret = regmap_read(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), + &bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", ret); + return ret; + } + + ret = regmap_read(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), &mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slot_width = aif_intf_cfg->slot_width_tx; + /* Prepare TX field values */ + tx_bw_fields = + ((QAIF_AIF_SAMPLE_WIDTH(bitwidth) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK) | + ((QAIF_AIF_SLOT_WIDTH(slot_width) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK); + + /* Clear TX fields, preserve RX fields, write new TX values */ + bit_width_cfg_val = + (bit_width_cfg_val & + ~QAIF_AUD_INTF_BIT_WIDTH_CFG_TX_FIELDS_MASK) | + tx_bw_fields; + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", + ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(idx), + aif_intf_cfg->slot_en_tx_mask); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG: %d\n", + ret); + return ret; + } + + frame_cfg_val = (slot_width * aif_intf_cfg->bits_per_lane) - 1; + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_FRAME_CFG_REG(idx), frame_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_FRAME_CFG_REG: %d\n", ret); + return ret; + } + + /* Clear TX field, preserve RX field */ + mi2s_cfg_val &= ~QAIF_AUD_INTF_MI2S_CFG_TX_FIELDS_MASK; + if (channels >= 2) { + /* Set new TX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_STEREO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK); + } else { + /* Set new TX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_MONO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK); + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), + mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Write to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + dev_err(dai->dev, "%s: TX bw_cfg=%x slot_en=%x frame=%x mi2s=%x\n", + __func__, bit_width_cfg_val, + aif_intf_cfg->slot_en_tx_mask, + frame_cfg_val, mi2s_cfg_val); + } else { + slot_width = aif_intf_cfg->slot_width_tx; + /* Prepare RX field values */ + rx_bw_fields = + ((QAIF_AIF_SAMPLE_WIDTH(bitwidth) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK) | + ((QAIF_AIF_SLOT_WIDTH(slot_width) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK); + + /* Clear RX fields, preserve TX fields, write new RX values */ + bit_width_cfg_val = + (bit_width_cfg_val & + ~QAIF_AUD_INTF_BIT_WIDTH_CFG_RX_FIELDS_MASK) | + rx_bw_fields; + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", + ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(idx), + aif_intf_cfg->slot_en_rx_mask); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG: %d\n", + ret); + return ret; + } + + frame_cfg_val = (slot_width * aif_intf_cfg->bits_per_lane) - 1; + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_FRAME_CFG_REG(idx), frame_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_FRAME_CFG_REG: %d\n", ret); + return ret; + } + + /* Clear RX field, preserve TX field */ + mi2s_cfg_val &= ~QAIF_AUD_INTF_MI2S_CFG_RX_FIELDS_MASK; + if (channels >= 2) { + /* Set new RX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_STEREO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK); + } else { + /* Set new RX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_MONO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK); + } + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), + mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Write to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + dev_err(dai->dev, "%s: RX bw_cfg=%x slot_en=%x frame=%x mi2s=%x\n", + __func__, bit_width_cfg_val, + aif_intf_cfg->slot_en_rx_mask, + frame_cfg_val, mi2s_cfg_val); + } + + if (ret) { + dev_err(dai->dev, "error writing to aif_intfctl channels mode: %d\n", + ret); + return ret; + } + + ret = clk_set_rate(drvdata->mi2s_bit_clk[idx], + rate * slot_width * aif_intf_cfg->bits_per_lane); + if (ret) { + dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", + rate * slot_width * aif_intf_cfg->bits_per_lane, ret); + return ret; + } + dev_dbg(dai->dev, "setting IBIT clock to %u\n", + rate * slot_width * aif_intf_cfg->bits_per_lane); + + if (!drvdata->mi2s_was_prepared[idx]) { + ret = clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + drvdata->mi2s_was_prepared[idx] = true; + + dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d\n", + __func__, substream->name, substream->stream); + snd_soc_dai_set_tdm_slot(codec_dai, 0x0f, 0b11, + aif_intf_cfg->bits_per_lane, slot_width); + snd_soc_dai_set_sysclk(codec_dai, 0, + rate * aif_intf_cfg->bits_per_lane * slot_width, + 0); + } + + return 0; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops = { + .probe = qaif_aif_cpu_daiops_probe, + .set_sysclk = qaif_aif_cpu_daiops_set_sysclk, + .startup = qaif_aif_cpu_daiops_startup, + .shutdown = qaif_aif_cpu_daiops_shutdown, + .hw_params = qaif_aif_cpu_daiops_hw_params, + .trigger = qaif_aif_cpu_daiops_trigger, + .prepare = qaif_aif_cpu_daiops_prepare, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops); + +static int asoc_qcom_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct qaif_variant *v = drvdata->variant; + int id = args->args[0]; + int ret = -EINVAL; + int i; + + for (i = 0; i < v->num_dai; i++) { + if (v->dai_driver[i].id == id) { + *dai_name = v->dai_driver[i].name; + ret = 0; + break; + } + } + + return ret; +} + +static const struct snd_soc_component_driver qaif_cpu_comp_driver = { + .name = "qaif-cpu", + .of_xlate_dai_name = asoc_qcom_of_xlate_dai_name, + .legacy_dai_naming = 1, +}; + +static bool __audio_qaif_regmap_accessible(struct device *dev, unsigned int reg, bool rw) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + int i; + + if (reg == QAIF_EE_OVERLAP_IRQ_EN_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_CLEAR_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_FORCE_REG) + return true; + + for (i = 0; i < DMA_TYPE_MAX; i++) { + //RDDMA IRQ + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i)) + return true; + + //WRDMA IRQ + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i)) + return true; + } + + for (i = 0; i < v->num_rddma; i++) { + if (reg == QAIF_RDDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_wrdma; i++) { + if (reg == QAIF_WRDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_codec_rddma; i++) { + if (reg == QAIF_CODEC_RDDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_codec_wrdma; i++) { + if (reg == QAIF_CODEC_WRDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + return true; +} + +static bool audio_qaif_regmap_writeable(struct device *dev, unsigned int reg) +{ + return __audio_qaif_regmap_accessible(dev, reg, QAIF_AIF_REG_WRITE); +} + +static bool audio_qaif_regmap_readable(struct device *dev, unsigned int reg) +{ + return __audio_qaif_regmap_accessible(dev, reg, QAIF_AIF_REG_READ); +} + +static bool audio_qaif_regmap_volatile(struct device *dev, unsigned int reg) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + int i; + + for (i = 0; i < DMA_TYPE_MAX; i++) { + //RDDMA IRQ + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + + //WRDMA IRQ + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + } + + for (i = 0; i < v->num_rddma; i++) + if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_wrdma; i++) + if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_codec_rddma; i++) + if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_codec_wrdma; i++) + if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + + return true; +} + +static struct regmap_config audio_qaif_regmap_config = { + .name = "audio_qaif_cpu", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .writeable_reg = audio_qaif_regmap_writeable, + .readable_reg = audio_qaif_regmap_readable, + .volatile_reg = audio_qaif_regmap_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static int of_qaif_parse_aif_intf_cfg(struct device *dev, + struct qaif_drv_data *data) +{ + struct qaif_variant *v = data->variant; + struct device_node *np = dev->of_node; + struct device_node *intf_np; + struct qaif_aif_config *cfg; + const __be32 *lane_cfg_prop; + int num_interfaces, ret, i, j; + int lane_cfg_len; + int dai_id, intf_idx; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + /* Get count of interface phandles from aif-interface property */ + num_interfaces = of_count_phandle_with_args(np, "aif-interface", NULL); + if (num_interfaces <= 0) { + dev_err(dev, "No aif-interface property found or invalid: %d\n", num_interfaces); + return -EINVAL; + } + + if (num_interfaces > QAIF_MAX_AIF_CFG_CNT) { + dev_warn(dev, "Too many interfaces (%d), limiting to %d\n", + num_interfaces, QAIF_MAX_AIF_CFG_CNT); + num_interfaces = QAIF_MAX_AIF_CFG_CNT; + } + + dev_info(dev, "Found %d AIF interfaces to parse\n", num_interfaces); + + /* Parse each interface node */ + for (i = 0; i < num_interfaces; i++) { + intf_np = of_parse_phandle(np, "aif-interface", i); + if (!intf_np) { + dev_err(dev, "Failed to get interface node %d\n", i); + continue; + } + + dev_dbg(dev, "Parsing interface %d: %s\n", i, intf_np->name); + + ret = of_property_read_u32(intf_np, "qcom,qaif-intf-dai-id", &dai_id); + if (ret) { + dev_err(dev, "Missing dai-id for interface %d: %s ===\n", i, intf_np->name); + continue; + } + + if (v->get_dma_idx) { + intf_idx = v->get_dma_idx(dai_id); + if (intf_idx < 0) { + dev_err(dev, + "invalid intf idx for : %d: %s ===\n", + i, intf_np->name); + continue; + } + } else { + dev_err(dev, "can not get intf idx for : %d: %s ===\n", i, intf_np->name); + return -EINVAL; + } + cfg = &v->aif_intf_cfg[intf_idx]; + + /* Parse sync configuration */ + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-mode", &cfg->sync_mode); + if (ret) { + dev_warn(dev, "Missing sync-mode for interface %d\n", i); + cfg->sync_mode = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-src", &cfg->sync_src); + if (ret) { + dev_warn(dev, "Missing sync-src for interface %d\n", i); + cfg->sync_src = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-invert-sync", &cfg->invert_sync); + if (ret) { + dev_warn(dev, "Missing invert-sync for interface %d\n", i); + cfg->invert_sync = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-delay", &cfg->sync_delay); + if (ret) { + dev_warn(dev, "Missing sync-delay for interface %d\n", i); + cfg->sync_delay = 0; + } + + /* Parse slot and sample width configuration */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-width-rx", + &cfg->slot_width_rx); + if (ret) { + dev_warn(dev, "Missing slot-width-rx for interface %d\n", i); + cfg->slot_width_rx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-width-tx", + &cfg->slot_width_tx); + if (ret) { + dev_warn(dev, "Missing slot-width-tx for interface %d\n", i); + cfg->slot_width_tx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-sample-width-rx", + &cfg->sample_width_rx); + if (ret) { + dev_warn(dev, "Missing sample-width-rx for interface %d\n", i); + cfg->sample_width_rx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-sample-width-tx", + &cfg->sample_width_tx); + if (ret) { + dev_warn(dev, "Missing sample-width-tx for interface %d\n", i); + cfg->sample_width_tx = 0; + } + + /* Parse slot enable masks */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-en-rx-mask", + &cfg->slot_en_rx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-rx-mask for interface %d\n", i); + cfg->slot_en_rx_mask = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-en-tx-mask", + &cfg->slot_en_tx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-tx-mask for interface %d\n", i); + cfg->slot_en_tx_mask = 0; + } + + /* Parse control configuration */ + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-loopback-en", &cfg->loopback_en); + if (ret) { + dev_warn(dev, "Missing loopback-en for interface %d\n", i); + cfg->loopback_en = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-ctrl-data-oe", + &cfg->ctrl_data_oe); + if (ret) { + dev_warn(dev, "Missing ctrl-data-oe for interface %d\n", i); + cfg->ctrl_data_oe = 0; + } + + /* Parse lane configuration */ + lane_cfg_prop = of_get_property(intf_np, + "qcom,qaif-aif-lane-config", + &lane_cfg_len); + if (lane_cfg_prop) { + /* Each lane config has 2 u32 values: enable and direction */ + cfg->num_lanes = lane_cfg_len / (2 * sizeof(u32)); + if (cfg->num_lanes > QAIF_MAX_LANES) { + dev_warn(dev, "Too many lanes (%d), limiting to %d\n", + cfg->num_lanes, QAIF_MAX_LANES); + cfg->num_lanes = QAIF_MAX_LANES; + } + + for (j = 0; j < cfg->num_lanes; j++) { + cfg->lane_cfg[j].enable = + be32_to_cpup(lane_cfg_prop + (j * 2)); + if (cfg->lane_cfg[j].enable) + cfg->lane_en_mask |= BIT(j); + /* Set bit j for lane enable */ + + cfg->lane_cfg[j].direction = + be32_to_cpup(lane_cfg_prop + (j * 2 + 1)); + if (cfg->lane_cfg[j].direction) + cfg->lane_dir_mask |= BIT(j); + /* Set bit j for RX direction */ + } + + } else { + dev_warn(dev, "Missing lane-config for interface %d\n", i); + cfg->num_lanes = 0; + } + + /* Parse mono/stereo mode */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-mono-mode-tx", + &cfg->mono_mode_tx); + if (ret) { + dev_warn(dev, "Missing mono-mode-tx for interface %d\n", i); + cfg->mono_mode_tx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-mono-mode-rx", + &cfg->mono_mode_rx); + if (ret) { + dev_warn(dev, "Missing mono-mode-rx for interface %d\n", i); + cfg->mono_mode_rx = 0; + } + + /* Parse frame configuration */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-full-cycle-en", + &cfg->full_cycle_en); + if (ret) { + dev_warn(dev, "Missing full-cycle-en for interface %d\n", i); + cfg->full_cycle_en = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-bits-per-lane", + &cfg->bits_per_lane); + if (ret) { + dev_warn(dev, "Missing bits-per-lane for interface %d\n", i); + cfg->bits_per_lane = 0; + } + + /* Debug dump of parsed properties. */ + dev_dbg(dev, "Interface %d configuration:\n", i); + dev_dbg(dev, " Node name: %s\n", intf_np->name); + + /* Sync configuration */ + dev_dbg(dev, " Sync Configuration:\n"); + dev_dbg(dev, " sync_mode = %u\n", cfg->sync_mode); + dev_dbg(dev, " sync_src = %u\n", cfg->sync_src); + dev_dbg(dev, " invert_sync = %u\n", cfg->invert_sync); + dev_dbg(dev, " sync_delay = %u\n", cfg->sync_delay); + + /* Slot and sample width */ + dev_dbg(dev, " Width Configuration:\n"); + dev_dbg(dev, " slot_width_rx = %u\n", cfg->slot_width_rx); + dev_dbg(dev, " slot_width_tx = %u\n", cfg->slot_width_tx); + dev_dbg(dev, " sample_width_rx= %u\n", cfg->sample_width_rx); + dev_dbg(dev, " sample_width_tx= %u\n", cfg->sample_width_tx); + + /* Slot enable masks */ + dev_dbg(dev, " Slot Enable Masks:\n"); + dev_dbg(dev, " slot_en_rx_mask= 0x%08X\n", cfg->slot_en_rx_mask); + dev_dbg(dev, " slot_en_tx_mask= 0x%08X\n", cfg->slot_en_tx_mask); + + /* Control configuration */ + dev_dbg(dev, " Control Configuration:\n"); + dev_dbg(dev, " loopback_en = %u\n", cfg->loopback_en); + dev_dbg(dev, " ctrl_data_oe = %u\n", cfg->ctrl_data_oe); + + /* Lane configuration */ + dev_dbg(dev, " Lane Configuration (num_lanes=%u):\n", cfg->num_lanes); + for (j = 0; j < cfg->num_lanes; j++) { + dev_dbg(dev, " Lane %d: enable=%u, direction=%u (%s)\n", + j, cfg->lane_cfg[j].enable, cfg->lane_cfg[j].direction, + cfg->lane_cfg[j].direction ? "RX_MIC" : "TX_SPKR"); + } + dev_dbg(dev, " Lane Configuration (lane_en_mask=0x%x):\n", cfg->lane_en_mask); + dev_dbg(dev, " Lane Configuration (lane_dir_mask=0x%x):\n", cfg->lane_dir_mask); + + /* Mono/Stereo mode */ + dev_dbg(dev, " Mono/Stereo Mode:\n"); + dev_dbg(dev, " mono_mode_tx = %u (%s)\n", + cfg->mono_mode_tx, cfg->mono_mode_tx ? "MONO" : "STEREO"); + dev_dbg(dev, " mono_mode_rx = %u (%s)\n", + cfg->mono_mode_rx, cfg->mono_mode_rx ? "MONO" : "STEREO"); + + /* Frame configuration */ + dev_dbg(dev, " Frame Configuration:\n"); + dev_dbg(dev, " full_cycle_en = %u\n", cfg->full_cycle_en); + dev_dbg(dev, " bits_per_lane = %u\n", cfg->bits_per_lane); + + dev_dbg(dev, "End interface %d\n", i); + + of_node_put(intf_np); + } + + dev_info(dev, "Successfully parsed %d AIF interfaces\n", num_interfaces); + return 0; +} + +static int of_qaif_cdc_dma_clks_parse(struct device *dev, + struct qaif_drv_data *data) +{ + data->aud_dma_clk = devm_clk_get(dev, "audio_core_cc_aud_dma_clk"); + if (IS_ERR(data->aud_dma_clk)) + return PTR_ERR(data->aud_dma_clk); + + data->aud_dma_mem_clk = devm_clk_get(dev, "audio_core_cc_aud_dma_mem_clk"); + if (IS_ERR(data->aud_dma_mem_clk)) + return PTR_ERR(data->aud_dma_mem_clk); + + return 0; +} + +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata; + struct resource *res; + struct qaif_variant *variant; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + int ret, i, dai_id, idx; + bool variant_init_done = false; + + drvdata = devm_kzalloc(dev, sizeof(struct qaif_drv_data), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + platform_set_drvdata(pdev, drvdata); + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + drvdata->variant = (struct qaif_variant *)match->data; + variant = drvdata->variant; + if (!variant) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + + ret = of_qaif_parse_aif_intf_cfg(dev, drvdata); + if (ret) { + dev_err(dev, "Failed to parse aif interfaces: %d\n", ret); + return -EINVAL; + } + + drvdata->audio_qaif = + devm_platform_ioremap_resource_byname(pdev, "audio-qaif-core"); + if (IS_ERR(drvdata->audio_qaif)) + return PTR_ERR(drvdata->audio_qaif); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audio-qaif-core"); + if (!res) + return -EINVAL; + + audio_qaif_regmap_config.max_register = resource_size(res); + + drvdata->audio_qaif_map = devm_regmap_init_mmio(dev, drvdata->audio_qaif, + &audio_qaif_regmap_config); + if (IS_ERR(drvdata->audio_qaif_map)) + return PTR_ERR(drvdata->audio_qaif_map); + + ret = of_qaif_cdc_dma_clks_parse(dev, drvdata); + if (ret) { + dev_err(dev, "failed to get cdc dma clocks %d\n", ret); + return ret; + } + + if (variant->init) { + ret = variant->init(pdev); + if (ret) { + dev_err(dev, "error initializing variant: %d\n", ret); + return ret; + } + variant_init_done = true; + } + + for (i = 0; i < variant->num_dai; i++) { + dai_id = variant->dai_driver[i].id; + if (is_cif_dma_port(dai_id)) + continue; + idx = variant->get_dma_idx(dai_id); + if (idx < 0) + continue; + + drvdata->mi2s_bit_clk[idx] = devm_clk_get(dev, + variant->dai_bit_clk_names[idx]); + if (IS_ERR(drvdata->mi2s_bit_clk[idx])) { + dev_err(dev, + "error getting %s: %ld\n", + variant->dai_bit_clk_names[idx], + PTR_ERR(drvdata->mi2s_bit_clk[idx])); + ret = PTR_ERR(drvdata->mi2s_bit_clk[idx]); + goto err; + } + } + + ret = qaif_aif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + /* Initialize bitfields for dai AIF CFG register */ + ret = qaif_aif_cfg_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init aif_intfctl field: %d\n", ret); + goto err; + } + + ret = qaif_cif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + ret = devm_snd_soc_register_component(dev, &qaif_cpu_comp_driver, + variant->dai_driver, + variant->num_dai); + if (ret) { + dev_err(dev, "error registering cpu driver: %d\n", ret); + goto err; + } + + ret = asoc_qcom_qaif_platform_register(pdev); + if (ret) { + dev_err(dev, "error registering platform driver: %d\n", ret); + goto err; + } + dev_info(&pdev->dev, "%s: QAIF CPU-Platform Driver Registered Successfully\n", __func__); +err: + if (ret && variant_init_done && variant->exit) + variant->exit(pdev); + return ret; +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_probe); + +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_remove); + +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_shutdown); + +MODULE_DESCRIPTION("QTi QAIF CPU Driver"); +MODULE_LICENSE("GPL"); From 3f879b595d5ac688fcf79976e81576b8f7cfde46 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Fri, 29 May 2026 11:46:24 +0530 Subject: [PATCH 0995/1058] ASoC: qcom: Add QAIF platform driver Add platform driver for the Qualcomm Technologies Qualcomm Audio Interface (QAIF) ports. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/qaif-platform.c | 1219 ++++++++++++++++++++++++++++++++ 1 file changed, 1219 insertions(+) create mode 100644 sound/soc/qcom/qaif-platform.c diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c new file mode 100644 index 0000000000000..545c2fd857d20 --- /dev/null +++ b/sound/soc/qcom/qaif-platform.c @@ -0,0 +1,1219 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-platform.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" + +#define DRV_NAME "qaif-platform" + +/* 20 ms @ 48kHz S16 stereo = 3840 bytes */ +#define QAIF_PLATFORM_BUFFER_MIN_SIZE (960 * 2 * 2) +/* min period = 960 frames @ S16 stereo = 3840 bytes */ +#define QAIF_PLATFORM_PERIOD_BYTES_MIN (960 * 2 * 2) +/* 80 ms = 15360 bytes */ +#define QAIF_PLATFORM_BUFFER_SIZE (4 * QAIF_PLATFORM_BUFFER_MIN_SIZE) +#define QAIF_PLATFORM_PERIODS_MIN 2 +#define QAIF_PLATFORM_PERIODS_MAX 4 // 4 × 3840 = 15360 = buffer_bytes_max + +#define QAIF_SMMU_SID_OFFSET 32 + +static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); +static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); +//static irqreturn_t qaif_aud_inf_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); + +static int qaif_init(struct snd_soc_component *component); + +static const struct snd_pcm_hardware qaif_platform_aif_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN, + .periods_min = QAIF_PLATFORM_PERIODS_MIN, + .periods_max = QAIF_PLATFORM_PERIODS_MAX, + .fifo_size = 0, +}; + +static const struct snd_pcm_hardware qaif_platform_cif_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN, + .periods_min = QAIF_PLATFORM_PERIODS_MIN, + .periods_max = QAIF_PLATFORM_PERIODS_MAX, + .fifo_size = 0, +}; + +static const struct qaif_irq_map qaif_irq_clients[] = { + { QAIF_CLIENT_ID_AIF_DMA, QAIF_BITMASK_AIF_RDDMA_WRDMA, qaif_aif_irq_handler}, + { QAIF_CLIENT_ID_CIF_DMA, QAIF_BITMASK_CIF_RDDMA_WRDMA, qaif_cif_irq_handler}, + { QAIF_CLIENT_ID_AUD_INF, QAIF_BITMASK_AUD_INF, NULL}, +}; + +static const u32 QAIF_ALL_CLIENTS_MASK = + QAIF_BITMASK_AIF_RDDMA_WRDMA | + QAIF_BITMASK_CIF_RDDMA_WRDMA | + QAIF_BITMASK_AUD_INF; + +static struct qaif_dma_mem_info *qaif_mem_alloc_attach(struct snd_soc_component *component, + size_t alloc_size) +{ + struct device *dev = component->dev; + struct qaif_dma_mem_info *dma_mem_info; + + dma_mem_info = kzalloc_obj(*dma_mem_info, GFP_KERNEL); + if (!dma_mem_info) + return NULL; + + dma_mem_info->alloc_size = alloc_size; + + /* + * dma_alloc_coherent: allocates cache-coherent memory, returns + * CPU virtual address and fills dma_addr with the DMA/IOVA address. + */ + dma_mem_info->vaddr = dma_alloc_coherent(dev, alloc_size, + &dma_mem_info->dma_addr, + GFP_KERNEL); + if (!dma_mem_info->vaddr) { + dev_err(dev, "dma_alloc_coherent failed for %zu bytes\n", alloc_size); + kfree(dma_mem_info); + return NULL; + } + + dev_dbg(dev, "%s: dma_addr=%llx vaddr=%p\n", __func__, + dma_mem_info->dma_addr, dma_mem_info->vaddr); + return dma_mem_info; +} + +static void qaif_mem_dealloc_detach(struct device *dev, + struct qaif_dma_mem_info *dma_info) +{ + if (!dma_info) + return; + + if (dma_info->vaddr) + dma_free_coherent(dev, dma_info->alloc_size, + dma_info->vaddr, dma_info->dma_addr); + + kfree(dma_info); +} + +static struct qaif_dmactl *qaif_get_dmactl_handle(const struct snd_pcm_substream *substream, + struct snd_soc_component *component) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct qaif_dmactl *dmactl = NULL; + struct qaif_variant *v = drvdata->variant; + + switch (cpu_dai->driver->id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dmactl = v->aif_rd_dmactl; + else + dmactl = v->aif_wr_dmactl; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + dmactl = v->cif_rd_dmactl; + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + dmactl = v->cif_wr_dmactl; + break; + } + + return dmactl; +} + +static int qaif_platform_pcmops_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct snd_dma_buffer *buf; + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + int ret, stream_dma_idx, dir = substream->stream; + struct qaif_pcm_data *data; + struct qaif_dmactl *dmactl; + struct qaif_dma_mem_info *dma_mem_info; + struct regmap *map; + unsigned int dai_id = cpu_dai->driver->id; + + pr_err("%s:%d: dai_id=%u stream=%d\n", + __func__, __LINE__, dai_id, dir); + + if (v->alloc_stream_dma_idx) + stream_dma_idx = v->alloc_stream_dma_idx(drvdata, dir, dai_id); + else + return -EINVAL; + + if (stream_dma_idx < 0) + return stream_dma_idx; + data = kzalloc_obj(*data, GFP_KERNEL); + if (!data) + return -ENOMEM; + + //data->i2s_port = cpu_dai->driver->id; + data->stream_dma_idx = stream_dma_idx; + + runtime->private_data = data; + map = drvdata->audio_qaif_map; + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) { + kfree(data); + return -EINVAL; + } + buf = &substream->dma_buffer; + buf->dev.dev = component->dev; + buf->private_data = NULL; + /* Assign DMA buffer pointers */ + buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; + + dma_mem_info = qaif_mem_alloc_attach(component, + qaif_platform_aif_hardware.buffer_bytes_max); + if (!dma_mem_info) + return -ENOMEM; + + clk_prepare_enable(drvdata->aud_dma_clk); + clk_prepare_enable(drvdata->aud_dma_mem_clk); + + ret = qaif_init(component); + if (ret) { + dev_err(soc_runtime->dev, "qaif_init failed: %d\n", ret); + return -EINVAL; + } + drvdata->qaif_init_ref_cnt++; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + drvdata->aif_substream[stream_dma_idx] = substream; + drvdata->aif_dma_heap[stream_dma_idx] = dma_mem_info; + buf->bytes = qaif_platform_aif_hardware.buffer_bytes_max; + buf->addr = drvdata->aif_dma_heap[stream_dma_idx]->dma_addr; + buf->area = (unsigned char *)drvdata->aif_dma_heap[stream_dma_idx]->vaddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_aif_hardware); + runtime->dma_bytes = qaif_platform_aif_hardware.buffer_bytes_max; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + drvdata->cif_substream[stream_dma_idx] = substream; + drvdata->cif_dma_heap[stream_dma_idx] = dma_mem_info; + buf->bytes = qaif_platform_cif_hardware.buffer_bytes_max; + buf->addr = drvdata->cif_dma_heap[stream_dma_idx]->dma_addr; + buf->area = (unsigned char *)drvdata->cif_dma_heap[stream_dma_idx]->vaddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_cif_hardware); + runtime->dma_bytes = qaif_platform_cif_hardware.buffer_bytes_max; + break; + default: + break; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + kfree(data); + dev_err(soc_runtime->dev, "setting constraints failed: %d\n", + ret); + return -EINVAL; + } + dev_dbg(soc_runtime->dev, + "%s: runtime info - dma_area=%p, dma_addr=0x%llx, dma_bytes=%zu\n", + __func__, + runtime->dma_area, + (unsigned long long)runtime->dma_addr, + runtime->dma_bytes); + pr_err("%s:%d: stream_dma_idx=%d qaif_init_ref_cnt=%d\n", + __func__, __LINE__, stream_dma_idx, drvdata->qaif_init_ref_cnt); + + return 0; +} + +static int qaif_platform_pcmops_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_pcm_data *data; + unsigned int dai_id = cpu_dai->driver->id; + + data = runtime->private_data; + pr_err("%s:%d: dai_id=%u stream=%d stream_dma_idx=%d\n", + __func__, __LINE__, dai_id, substream->stream, + data ? data->stream_dma_idx : -1); + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + drvdata->aif_substream[data->stream_dma_idx] = NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->aif_dma_heap[data->stream_dma_idx]); + drvdata->aif_dma_heap[data->stream_dma_idx] = NULL; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + drvdata->cif_substream[data->stream_dma_idx] = NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->cif_dma_heap[data->stream_dma_idx]); + drvdata->cif_dma_heap[data->stream_dma_idx] = NULL; + break; + default: + break; + } + + if (drvdata->qaif_init_ref_cnt > 0) + drvdata->qaif_init_ref_cnt--; + else + dev_dbg(component->dev, "%s: QAIF init ref cnt: %d, skipping decrement\n", + __func__, drvdata->qaif_init_ref_cnt); + + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id); + clk_disable_unprepare(drvdata->aud_dma_clk); + clk_disable_unprepare(drvdata->aud_dma_mem_clk); + kfree(data); + pr_err("%s:%d: done qaif_init_ref_cnt=%d\n", + __func__, __LINE__, drvdata->qaif_init_ref_cnt); + return 0; +} + +static int qaif_platform_pcmops_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + unsigned int dai_id = cpu_dai->driver->id; + int idx; + int ret; + + pr_err("%s:%d: dai_id=%u stream=%d channels=%u rate=%u\n", + __func__, __LINE__, dai_id, substream->stream, + params_channels(params), params_rate(params)); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_fields_write(dmactl->burst4, idx, QAIF_DMACTL_BURSTEN); + if (ret) { + dev_err(soc_runtime->dev, "error updating burst4 field: %d\n", ret); + return ret; + } + + ret = regmap_fields_write(dmactl->shram_wm, idx, QAIF_DMACTL_WM_5); + if (ret) { + dev_err(soc_runtime->dev, "error updating shram_wm field: %d\n", ret); + return ret; + } + + pr_err("%s:%d: configured idx=%d\n", __func__, __LINE__, idx); + return 0; +} + +static int qaif_platform_pcmops_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + unsigned int reg; + int ret, idx; + unsigned int dai_id = cpu_dai->driver->id; + struct regmap *map = drvdata->audio_qaif_map; + struct qaif_dmactl *dmactl; + + pr_err("%s:%d: dai_id=%u stream=%d\n", + __func__, __LINE__, dai_id, substream->stream); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + reg = QAIF_DMACFG_REG(v, idx, substream->stream, dai_id); + ret = regmap_write(map, reg, 0); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + pr_err("%s:%d: idx=%d ret=%d\n", __func__, __LINE__, idx, ret); + return ret; +} + +static int qaif_platform_pcmops_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int bitwidth = 32;//snd_pcm_format_width(runtime->format); + unsigned int channels = runtime->channels; + unsigned int rate = runtime->rate; + int ret, idx, dir = substream->stream; + unsigned int dai_id = cpu_dai->driver->id; + + pr_err("%s:%d: dai_id=%u stream=%d rate=%u channels=%u\n", + __func__, __LINE__, dai_id, dir, rate, channels); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + map = drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + clk_set_rate(drvdata->aud_dma_clk, rate * bitwidth * channels * 100); + clk_set_rate(drvdata->aud_dma_mem_clk, rate * bitwidth * channels * 100); + dev_dbg(soc_runtime->dev, "setting aud_dma_clk & aud_dma_mem_clk to %u\n", + rate * bitwidth * channels * 100); + + ret = regmap_write(map, QAIF_SID_MAP_REG(dir, dai_id), + drvdata->smmu_csid_bits); + if (ret) { + dev_err(soc_runtime->dev, "error writing to SID MAP reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMABASE_REG(v, idx, dir, dai_id), + runtime->dma_addr); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMABUFF_REG(v, idx, dir, dai_id), + (snd_pcm_lib_buffer_bytes(substream) >> 3) - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMAPER_LEN_REG(v, idx, dir, dai_id), + (snd_pcm_lib_period_bytes(substream) >> 3) - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", + ret); + return ret; + } + + pr_err("%s:%d: idx=%d dma_addr=0x%llx buf_bytes=%zu period_bytes=%zu\n", + __func__, __LINE__, idx, (unsigned long long)runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream)); + return 0; +} + +static int qaif_platform_irq_clear(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irqclr = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write(map, QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, irq_type), val_irqclr); + ret |= regmap_write(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, irq_type), + val_irqclr); + ret |= regmap_write(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type), + val_irqclr); + } else { + ret |= regmap_write(map, QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, irq_type), val_irqclr); + ret |= regmap_write(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, irq_type), + val_irqclr); + ret |= regmap_write(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type), + val_irqclr); + } + return ret; +} + +static int qaif_platform_irq_enable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irqen = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + } else { + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + } + return ret; +} + +static int qaif_platform_irq_disable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irq_disable = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + } else { + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + } + return ret; +} + +static int qaif_platform_pcmops_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int ret, idx; + unsigned int dai_id = cpu_dai->driver->id; + + //pr_err("%s:%d: dai_id=%u stream=%d cmd=%d\n", + // __func__, __LINE__, dai_id, substream->stream, cmd); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + map = drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK_ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + ret = qaif_platform_irq_clear(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret = qaif_platform_irq_enable(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + ret = qaif_platform_irq_clear(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret = qaif_platform_irq_enable(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); + return -EINVAL; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK_OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + ret = qaif_platform_irq_disable(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + ret = qaif_platform_irq_disable(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); + return -EINVAL; + } + break; + } + pr_err("%s:%d: cmd=%d idx=%d ret=%d\n", + __func__, __LINE__, cmd, idx, ret); + return 0; +} + +static snd_pcm_uframes_t qaif_platform_pcmops_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + unsigned int base_addr, curr_addr; + int ret, idx, dir = substream->stream; + struct regmap *map; + unsigned int dai_id = cpu_dai->driver->id; + + //pr_err("%s:%d: dai_id=%u stream=%d\n", + // __func__, __LINE__, dai_id, dir); + + map = drvdata->audio_qaif_map; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_read(map, + QAIF_DMABASE_REG(v, idx, dir, dai_id), &base_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmabase reg: %d\n", ret); + return ret; + } + + ret = regmap_read(map, + QAIF_DMACURR_REG(v, idx, dir, dai_id), &curr_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmacurr reg: %d\n", ret); + return ret; + } + + return bytes_to_frames(substream->runtime, curr_addr - base_addr); +} + +static int qaif_platform_cdc_dma_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long size, offset; + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + size = vma->vm_end - vma->vm_start; + offset = vma->vm_pgoff << PAGE_SHIFT; + return io_remap_pfn_range(vma, vma->vm_start, + (runtime->dma_addr + offset) >> PAGE_SHIFT, + size, vma->vm_page_prot); +} + +static int qaif_platform_pcmops_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + unsigned int dai_id = cpu_dai->driver->id; + + if (is_cif_dma_port(dai_id)) + return qaif_platform_cdc_dma_mmap(substream, vma); + + return snd_pcm_lib_default_mmap(substream, vma); +} + +static irqreturn_t qaif_process_dma_irq(struct qaif_drv_data *drvdata, + u32 stat_reg_addr, + u32 clr_reg_addr, + enum qaif_irq_type_t irq_type, + enum dma_type dma_type, + enum qaif_irq irq, + struct snd_pcm_substream **substream) +{ + const struct qaif_variant *v = drvdata->variant; + struct snd_pcm_substream *stream = NULL; + unsigned int reg = 0; + int dma_idx, stream_dma_idx, rv, num_dma = 0; + int stream_offset = (dma_type == DMA_TYPE_WRDMA) ? v->wrdma_start : 0; + irqreturn_t ret = IRQ_NONE; + u32 mask = 0; + + num_dma = (irq_type == QAIF_AIF_IRQ) ? v->num_rddma : v->num_codec_rddma; + mask = GENMASK(num_dma - 1, 0); + // Read Status + rv = regmap_read(drvdata->audio_qaif_map, stat_reg_addr, ®); + if (rv) { + pr_err("QAIF IRQ: error reading stat reg 0x%x: %d\n", stat_reg_addr, rv); + return IRQ_NONE; + } + + /* Writing the same reg that we just read from the status register, + * SPF also clears before handling. + */ + regmap_write(drvdata->audio_qaif_map, clr_reg_addr, reg & mask); + + for (dma_idx = 0; dma_idx < num_dma; dma_idx++) { + stream_dma_idx = dma_idx + stream_offset; + // Check if bit is set AND substream exists + if ((reg & BIT(dma_idx)) && substream[stream_dma_idx]) { + stream = substream[stream_dma_idx]; + switch (irq) { + case QAIF_IRQ_PERIOD: + snd_pcm_period_elapsed(stream); + ret = IRQ_HANDLED; + break; + + case QAIF_IRQ_OVERFLOW: + case QAIF_IRQ_UNDERFLOW: + // snd_pcm_stop_xrun(stream); + pr_warn_ratelimited("QAIF DMA xRun warning\n"); + ret = IRQ_HANDLED; + break; + + case QAIF_IRQ_ERROR: + snd_pcm_stop(stream, SNDRV_PCM_STATE_DISCONNECTED); + pr_err("QAIF Bus error\n"); + ret = IRQ_HANDLED; + break; + } + } + } + return ret; +} + +static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status) +{ + const struct qaif_variant *v = drvdata->variant; + irqreturn_t ret = IRQ_NONE; + struct snd_pcm_substream **substream = drvdata->aif_substream; + + // period_irq handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + // OVERFLOQW & underflow handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + // Bus error handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_ERROR, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + return ret; +} + +static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status) +{ + const struct qaif_variant *v = drvdata->variant; + irqreturn_t ret = IRQ_NONE; + struct snd_pcm_substream **substream = drvdata->cif_substream; + + // period_irq handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + + return ret; +} + +static irqreturn_t asoc_platform_qaif_irq(int irq, void *data) +{ + struct qaif_drv_data *drvdata = data; + const struct qaif_variant *v = drvdata->variant; + u32 summary_irq_status; + int rv, client; + irqreturn_t ret = IRQ_NONE; + + rv = regmap_read(drvdata->audio_qaif_map, + QAIF_SUMMARY_IRQSTAT_REG(v), &summary_irq_status); + if (rv) { + pr_err("error reading from irqstat reg: %d\n", rv); + return IRQ_NONE; + } + pr_debug("%s: summary_irq_status =0x%08x\n", __func__, summary_irq_status); + if (!(summary_irq_status & QAIF_ALL_CLIENTS_MASK)) + return IRQ_NONE; + for (client = 0; client < ARRAY_SIZE(qaif_irq_clients); client++) { + /* Check if the bits for this specific client_id are set in the register */ + if (summary_irq_status & qaif_irq_clients[client].mask) + ret = qaif_irq_clients[client].client_irq_handler(drvdata, + summary_irq_status); + } + return ret; +} + +static int qaif_platform_pcmops_suspend(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + + map = drvdata->audio_qaif_map; + pr_err("%s:%d: suspend\n", __func__, __LINE__); + + regcache_cache_only(map, true); + regcache_mark_dirty(map); + clk_disable(drvdata->aud_dma_clk); + clk_disable(drvdata->aud_dma_mem_clk); + return 0; +} + +static int qaif_platform_pcmops_resume(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + int ret; + + pr_err("%s:%d: resume\n", __func__, __LINE__); + clk_enable(drvdata->aud_dma_clk); + clk_enable(drvdata->aud_dma_mem_clk); + map = drvdata->audio_qaif_map; + + regcache_cache_only(map, false); + ret = regcache_sync(map); + if (ret) + dev_err(component->dev, "%s: regcache_sync failed: %d\n", + __func__, ret); + return ret; +} + +static int qaif_platform_copy(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int channel, + unsigned long pos, struct iov_iter *buf, + unsigned long bytes) +{ + struct snd_pcm_runtime *rt = substream->runtime; + size_t copied; + void *dma_buf; + + // rt->dma_area is the vaddr from iosys_vmap - regular kernel memory + dma_buf = (void *)(rt->dma_area + pos + + channel * (rt->dma_bytes / rt->channels)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + copied = copy_from_iter(dma_buf, bytes, buf); + if (copied != bytes) { + pr_err("DEBUG:%s:%d:Copy failed\n", __func__, __LINE__); + return -EFAULT; + } + } else { + copied = copy_to_iter(dma_buf, bytes, buf); + if (copied != bytes) { + pr_err("DEBUG:%s:%d:Copy failed\n", __func__, __LINE__); + return -EFAULT; + } + } + + return 0; +} + +static const struct snd_soc_component_driver qaif_component_driver = { + .name = DRV_NAME, + .open = qaif_platform_pcmops_open, + .close = qaif_platform_pcmops_close, + .hw_params = qaif_platform_pcmops_hw_params, + .hw_free = qaif_platform_pcmops_hw_free, + .prepare = qaif_platform_pcmops_prepare, + .trigger = qaif_platform_pcmops_trigger, + .pointer = qaif_platform_pcmops_pointer, + .mmap = qaif_platform_pcmops_mmap, + .suspend = qaif_platform_pcmops_suspend, + .resume = qaif_platform_pcmops_resume, + .copy = qaif_platform_copy, +}; + +/** + * qaif_map_ee_resource - Implements Steps 1-6 of Restrictions + * Maps GRP, INTF, RDDMA, WRDMA to the current EE. + */ +static int qaif_map_ee_resource(struct qaif_drv_data *drvdata) +{ + struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + int ret = 0; + u32 mask; + + mask = GENMASK(v->num_rddma - 1, 0); + ret |= regmap_write(map, QAIF_EE_RDDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_wrdma - 1, 0); + ret |= regmap_write(map, QAIF_EE_WRDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_intf - 1, 0); + ret |= regmap_write(map, QAIF_EE_INTF_MAP_REG(v), mask); + + mask = GENMASK(v->num_codec_rddma - 1, 0); + ret |= regmap_write(map, QAIF_EE_CODEC_RDDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_codec_wrdma - 1, 0); + ret |= regmap_write(map, QAIF_EE_CODEC_WRDMA_MAP_REG(v), mask); + + if (ret) + return ret; + return 0; +} + +static int qaif_map_dma_path(struct qaif_drv_data *drvdata) +{ + struct regmap *map = drvdata->audio_qaif_map; + struct qaif_variant *v = drvdata->variant; + int ret = 0; + int qxm_sel = v->qxm_type; + + if (qxm_sel != QXM0 && qxm_sel != QXM1) + return -EINVAL; + + ret |= regmap_write(map, QAIF_RDDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_WRDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_CODEC_RDDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_CODEC_WRDMA_MAP_QXM, qxm_sel); + + if (ret) + return ret; + + return 0; +} + +static int qaif_config_shram(struct qaif_drv_data *drvdata) +{ + struct qaif_variant *v = drvdata->variant; + u32 start_addr, shram_len; + int ret = 0, i = 0; + struct regmap *map = drvdata->audio_qaif_map; + + if (v->qxm_type != QXM0) + return -EINVAL; + //AIF RDDMA + start_addr = v->rddma_shram_start_addr[QAIF_AIF_DMA]; + shram_len = v->rddma_shram_len; + for (i = 0; i < v->num_rddma; i++) { + ret = regmap_write(map, + QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //AIF WRDMA + start_addr = v->wrdma_shram_start_addr[QAIF_AIF_DMA]; + shram_len = v->wrdma_shram_len; + for (i = 0; i < v->num_wrdma; i++) { + ret = regmap_write(map, + QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //CIF RDDMA + start_addr = v->rddma_shram_start_addr[QAIF_CIF_DMA]; + shram_len = v->rddma_shram_len; + for (i = 0; i < v->num_codec_rddma; i++) { + ret = regmap_write(map, + QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //CIF wrDMA + start_addr = v->wrdma_shram_start_addr[QAIF_CIF_DMA]; + shram_len = v->wrdma_shram_len; + for (i = 0; i < v->num_codec_wrdma; i++) { + ret = regmap_write(map, + QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + + if (ret) + return ret; + } + return 0; +} + +static int qaif_init(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + int ret = 0; + + if (drvdata->qaif_init_ref_cnt) { + dev_info(component->dev, "%s: QAIF init is done already: ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; + } + + ret = qaif_config_shram(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to config shram: %d\n", ret); + return ret; + } + + ret = qaif_map_ee_resource(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret); + return ret; + } + + ret = qaif_map_dma_path(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret); + return ret; + } + dev_dbg(component->dev, "%s: QAIF init is done ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; +} + +int asoc_qcom_qaif_platform_register(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + int ret = 0; + + if (!drvdata || !drvdata->variant) { + dev_err(&pdev->dev, "Invalid drvdata or variant\n"); + return -EINVAL; + } + + drvdata->smmu_csid_bits = 0; + + drvdata->audio_qaif_irq = platform_get_irq_byname(pdev, "qaif-irq-audio-core"); + if (drvdata->audio_qaif_irq < 0) + return -ENODEV; + + ret = devm_request_irq(&pdev->dev, drvdata->audio_qaif_irq, + asoc_platform_qaif_irq, IRQF_TRIGGER_HIGH, + "qaif-irq-audio-core", drvdata); + if (ret) { + dev_err(&pdev->dev, "irq request failed: %d\n", ret); + return ret; + } + drvdata->qaif_init_ref_cnt = 0; + dev_dbg(&pdev->dev, "%s: Register QAIF Platform\n", __func__); + return devm_snd_soc_register_component(&pdev->dev, + &qaif_component_driver, NULL, 0); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_platform_register); + +MODULE_DESCRIPTION("QTi QAIF Platform Driver"); +MODULE_LICENSE("GPL"); From cab30f10bdca041cf23fbf2090cc1b5d0b171d51 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Fri, 29 May 2026 11:48:09 +0530 Subject: [PATCH 0996/1058] ASoC: qcom: qaif-shikra: Add platform driver for qaif audio Add platform driver for configuring shikra qaif core I2S and DMA configuration to support playback & capture to external codecs connected over MI2S interface and soundwire interface. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/Kconfig | 11 + sound/soc/qcom/Makefile | 2 + sound/soc/qcom/qaif-shikra.c | 702 +++++++++++++++++++++++++++++++++++ 3 files changed, 715 insertions(+) create mode 100644 sound/soc/qcom/qaif-shikra.c diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index e6e24f3b99222..008b5ccae331a 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -71,6 +71,16 @@ config SND_SOC_QCOM_COMMON config SND_SOC_QCOM_SDW tristate +config SND_SOC_QCOM_QAIF + tristate "Qualcomm QAIF audio interface support" + depends on COMMON_CLK + select REGMAP_MMIO + help + Say Y or M to enable Qualcomm Audio Interface (QAIF) support + used on Shikra audio platforms. QAIF provides DMA-based audio + data transfer between the application processor and the audio + hardware interfaces (AIF and CIF). + config SND_SOC_QDSP6_COMMON tristate @@ -202,6 +212,7 @@ config SND_SOC_SC8280XP select SND_SOC_QDSP6 select SND_SOC_QCOM_COMMON select SND_SOC_QCOM_SDW + select SND_SOC_QCOM_QAIF help To add support for audio on Qualcomm Technologies Inc. SC8280XP SoC-based systems. diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 985ce2ae286ba..857bb2a032a2d 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -31,6 +31,7 @@ snd-soc-qcom-common-y := common.o snd-soc-qcom-sdw-y := sdw.o snd-soc-x1e80100-y := x1e80100.o snd-soc-qcom-offload-utils-objs := usb_offload_utils.o +snd-soc-qcom-qaif-y := qaif-cpu.o qaif-platform.o qaif-shikra.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o obj-$(CONFIG_SND_SOC_X1E80100) += snd-soc-x1e80100.o obj-$(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) += snd-soc-qcom-offload-utils.o +obj-$(CONFIG_SND_SOC_QCOM_QAIF) += snd-soc-qcom-qaif.o #DSP lib obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/ diff --git a/sound/soc/qcom/qaif-shikra.c b/sound/soc/qcom/qaif-shikra.c new file mode 100644 index 0000000000000..6e87ec7e22a16 --- /dev/null +++ b/sound/soc/qcom/qaif-shikra.c @@ -0,0 +1,702 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-shikra.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include "qaif.h" + +struct qaif_dmaidx_dai_map shikra_aif_dma_dai_map[] = { + { MI2S_QUATERNARY }, + { MI2S_QUINARY }, + { MI2S_SENARY }, + { MI2S_SEPTENARY } +}; + +struct qaif_dmaidx_dai_map shikra_cif_rx_dma_dai_map[] = { + { LPASS_CDC_DMA_RX0 }, + { LPASS_CDC_DMA_RX1 }, + { LPASS_CDC_DMA_RX2 }, + { LPASS_CDC_DMA_RX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_tx_dma_dai_map[] = { + { LPASS_CDC_DMA_TX0 }, + { LPASS_CDC_DMA_TX1 }, + { LPASS_CDC_DMA_TX2 }, + { LPASS_CDC_DMA_TX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_va_dma_dai_map[] = { + { LPASS_CDC_DMA_VA_TX0 }, + { LPASS_CDC_DMA_VA_TX1 }, + { LPASS_CDC_DMA_VA_TX2 }, + { LPASS_CDC_DMA_VA_TX3 } +}; + +static struct snd_soc_dai_driver shikra_qaif_cpu_dai_driver[] = { + { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Primary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Secondary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_TERTIARY, + .name = "Tertiary MI2S", + .playback = { + .stream_name = "Tertiary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Tertiary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_QUATERNARY, + .name = "Quaternary MI2S", + .playback = { + .stream_name = "Quaternary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Quaternary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_QUINARY, + .name = "Quinary MI2S", + .playback = { + .stream_name = "Quinary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Quinary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SENARY, + .name = "Senary MI2S", + .playback = { + .stream_name = "Senary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Senary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SEPTENARY, + .name = "Septenary MI2S", + .playback = { + .stream_name = "Septenary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Septenary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = LPASS_CDC_DMA_RX0, + .name = "CDC DMA RX0", + .playback = { + .stream_name = "WCD Playback0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_RX1, + .name = "CDC DMA RX1", + .playback = { + .stream_name = "WCD Playback1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_TX0, + .name = "CDC DMA TX0", + .capture = { + .stream_name = "WCD Capture0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_TX3, + .name = "CDC DMA TX3", + .capture = { + .stream_name = "WCD Capture1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_VA_TX0, + .name = "CDC DMA VA0", + .capture = { + .stream_name = "DMIC Capture0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_VA_TX1, + .name = "CDC DMA VA1", + .capture = { + .stream_name = "DMIC Capture1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, +}; + +static int shikra_qaif_get_dma_idx(unsigned int dai_id) +{ + int i; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + for (i = 0; i < ARRAY_SIZE(shikra_aif_dma_dai_map); i++) { + if (shikra_aif_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + for (i = 0; i < ARRAY_SIZE(shikra_cif_rx_dma_dai_map); i++) { + if (shikra_cif_rx_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + for (i = 0; i < ARRAY_SIZE(shikra_cif_tx_dma_dai_map); i++) { + if (shikra_cif_tx_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + for (i = 0; i < ARRAY_SIZE(shikra_cif_va_dma_dai_map); i++) { + if (shikra_cif_va_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + default: + pr_debug("DAI ID not Supported\n"); + break; + } + + pr_debug("DAI ID %u not found in map\n", dai_id); + return -EINVAL; +} + +static int shikra_qaif_alloc_stream_dma_idx(struct qaif_drv_data *drvdata, + int direction, unsigned int dai_id) +{ + struct qaif_variant *v = drvdata->variant; + int dma_idx; + int index = 0; + + if (!v) + return -EINVAL; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + dma_idx = shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + index = dma_idx; + if (index >= v->num_rddma) + return -EBUSY; + } else { + index = v->wrdma_start + dma_idx; + if (index >= v->wrdma_start + v->num_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->aif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + dma_idx = shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + index = dma_idx; + if (index >= v->num_codec_rddma) + return -EBUSY; + } else { + index = v->codec_wrdma_start + dma_idx; + if (index >= v->codec_wrdma_start + v->num_codec_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->cif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + return -EINVAL; + } + + return index; +} + +static int shikra_qaif_free_stream_dma_idx(struct qaif_drv_data *drvdata, + int index, unsigned int dai_id) +{ + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + clear_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + clear_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + break; + } + + return 0; +} + +static int shikra_qaif_init(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + struct qaif_variant *v = drvdata->variant; + struct device *dev = &pdev->dev; + int ret, i; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + if (v->num_clks == 0 || v->num_clks > 32) { + dev_err(dev, "Invalid clock count: %d\n", v->num_clks); + return -EINVAL; + } + drvdata->clks = devm_kcalloc(dev, v->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); + if (!drvdata->clks) + return -ENOMEM; + + drvdata->num_clks = v->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) + drvdata->clks[i].id = v->clk_name[i]; + + ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; + } + + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "shikra clk_enable failed\n"); + return ret; + } + + return 0; +} + +static int shikra_qaif_exit(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (!drvdata || !drvdata->clks) + return -EINVAL; + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static int __maybe_unused shikra_qaif_dev_resume(struct device *dev) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in resume\n"); + return -EINVAL; + } + return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); +} + +static int __maybe_unused shikra_qaif_dev_suspend(struct device *dev) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in suspend\n"); + return -EINVAL; + } + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static const struct dev_pm_ops shikra_qaif_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(shikra_qaif_dev_suspend, + shikra_qaif_dev_resume) +}; + +static struct qaif_variant shikra_qaif_data = { + .ee = 0, + .qaif_type = QAIF, + + .num_rddma = 4, + .num_wrdma = 4, + .wrdma_start = 4, + + .num_codec_rddma = 4, //RX + .num_codec_wrdma = 4, //TX + .codec_wrdma_start = 4, + .num_intf = 0, + + .rddma_reg_base = 0x8000, + .rddma_stride = 0x1000, + .codec_rddma_reg_base = 0xC000, + .codec_rddma_stride = 0x1000, + + .wrdma_reg_base = 0x11000, + .wrdma_stride = 0x1000, + .codec_wrdma_reg_base = 0x15000, + .codec_wrdma_stride = 0x1000, + + .rddma_irq_reg_base = 0x19000, + .rddma_irq_stride = 0x1000, + .codec_rddma_irq_reg_base = 0x191A0, + .codec_rddma_irq_stride = 0x1000, + + .wrdma_irq_reg_base = 0x19078, + .wrdma_irq_stride = 0x1000, + .codec_wrdma_irq_reg_base = 0x19290, + .codec_wrdma_irq_stride = 0x1000, + + .qxm_type = QXM0, + .rd_len = 512, + .rddma_shram_len = 64, + .rddma_shram_start_addr = {0, 256}, + .wr_len = 512, + .wrdma_shram_len = 64, + .wrdma_shram_start_addr = {0, 256}, + + /* ============================================================================ */ + /* AIF RDDMA (Audio Interface Read DMA) Register Fields */ + /* Base: 0x8000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x8000) */ + .rddma_enable = REG_FIELD_ID(0x8000, 0, 0, 4, 0x1000), /* ENABLE [0] */ + .rddma_reset = REG_FIELD_ID(0x8000, 4, 4, 4, 0x1000), /* RESET [4] */ + + /* CFG register (0x8004) */ + .rddma_shram_wm = REG_FIELD_ID(0x8004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .rddma_burst1 = REG_FIELD_ID(0x8004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .rddma_burst2 = REG_FIELD_ID(0x8004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .rddma_burst4 = REG_FIELD_ID(0x8004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .rddma_burst8 = REG_FIELD_ID(0x8004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .rddma_burst16 = REG_FIELD_ID(0x8004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .rddma_dma_dyncclk = REG_FIELD_ID(0x8004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .rddma_num_ot = REG_FIELD_ID(0x8004, 28, 29, 4, 0x1000), /* RDDMA_NUM_OT [29:28] */ + + /* ============================================================================ */ + /* AIF WRDMA (Audio Interface Write DMA) Register Fields */ + /* Base: 0x11000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x11000) */ + .wrdma_enable = REG_FIELD_ID(0x11000, 0, 0, 4, 0x1000), /* ENABLE [0] */ + .wrdma_reset = REG_FIELD_ID(0x11000, 4, 4, 4, 0x1000), /* RESET [4] */ + + /* CFG register (0x11004) */ + .wrdma_shram_wm = REG_FIELD_ID(0x11004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .wrdma_burst1 = REG_FIELD_ID(0x11004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .wrdma_burst2 = REG_FIELD_ID(0x11004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .wrdma_burst4 = REG_FIELD_ID(0x11004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .wrdma_burst8 = REG_FIELD_ID(0x11004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .wrdma_burst16 = REG_FIELD_ID(0x11004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .wrdma_dma_dyncclk = REG_FIELD_ID(0x11004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .wrdma_num_ot = REG_FIELD_ID(0x11004, 28, 29, 4, 0x1000), /* WRDMA_NUM_OT [29:28] */ + + /* ============================================================================ */ + /* CODEC RDDMA (RX/Playback) Register Fields */ + /* Base: 0xC000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0xC000) */ + .cif_rddma_enable = REG_FIELD_ID(0xC000, 0, 0, 4, 0x1000), + .cif_rddma_reset = REG_FIELD_ID(0xC000, 4, 4, 4, 0x1000), + + /* CFG register (0xC004) */ + .cif_rddma_shram_wm = REG_FIELD_ID(0xC004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .cif_rddma_burst1 = REG_FIELD_ID(0xC004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .cif_rddma_burst2 = REG_FIELD_ID(0xC004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .cif_rddma_burst4 = REG_FIELD_ID(0xC004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .cif_rddma_burst8 = REG_FIELD_ID(0xC004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .cif_rddma_burst16 = REG_FIELD_ID(0xC004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .cif_rddma_dma_dyncclk = REG_FIELD_ID(0xC004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .cif_rddma_num_ot = REG_FIELD_ID(0xC004, 28, 29, 4, 0x1000), /* RDDMA_NUM_OT [29:28] */ + + /* INTF_CFG register (0xC05C) */ + .cif_rddma_en_16bit_unpack = REG_FIELD_ID(0xC05C, 0, 0, 4, 0x1000), + /* ENABLE_16B_UNPACKING [0] */ + .cif_rddma_intf_dyncclk = REG_FIELD_ID(0xC05C, 2, 2, 4, 0x1000), /* DYNAMIC_CLOCK [2] */ + .cif_rddma_fs_out_gate = REG_FIELD_ID(0xC05C, 3, 3, 4, 0x1000), /* FS_OUT_GATING_EN [3] */ + .cif_rddma_fs_sel = REG_FIELD_ID(0xC05C, 4, 7, 4, 0x1000), /* FS_SEL [7:4] */ + .cif_rddma_fs_delay = REG_FIELD_ID(0xC05C, 8, 11, 4, 0x1000), /* FS_DELAY [11:8] */ + .cif_rddma_active_ch_en = REG_FIELD_ID(0xC05C, 12, 27, 4, 0x1000), + /* ACTIVE_CHANNEL_EN [27:12] */ + + /* ============================================================================ */ + /* CODEC WRDMA (TX/Capture) Register Fields */ + /* Base: 0x15000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x15000) */ + .cif_wrdma_enable = REG_FIELD_ID(0x15000, 0, 0, 4, 0x1000), + .cif_wrdma_reset = REG_FIELD_ID(0x15000, 4, 4, 4, 0x1000), + + /* CFG register (0x15004) */ + .cif_wrdma_shram_wm = REG_FIELD_ID(0x15004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .cif_wrdma_burst1 = REG_FIELD_ID(0x15004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .cif_wrdma_burst2 = REG_FIELD_ID(0x15004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .cif_wrdma_burst4 = REG_FIELD_ID(0x15004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .cif_wrdma_burst8 = REG_FIELD_ID(0x15004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .cif_wrdma_burst16 = REG_FIELD_ID(0x15004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .cif_wrdma_dma_dyncclk = REG_FIELD_ID(0x15004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .cif_wrdma_num_ot = REG_FIELD_ID(0x15004, 28, 29, 4, 0x1000), /* WRDMA_NUM_OT [29:28] */ + + /* INTF_CFG register (0x15058) */ + .cif_wrdma_en_16bit_unpack = REG_FIELD_ID(0x15058, 0, 0, 4, 0x1000), + /* ENABLE_16B_PACKING [0] */ + .cif_wrdma_intf_dyncclk = REG_FIELD_ID(0x15058, 2, 2, 4, 0x1000), /* DYNAMIC_CLOCK [2] */ + .cif_wrdma_fs_out_gate = REG_FIELD_ID(0x15058, 3, 3, 4, 0x1000), /* FS_OUT_GATING_EN [3] */ + .cif_wrdma_fs_sel = REG_FIELD_ID(0x15058, 4, 7, 4, 0x1000), /* FS_SEL [7:4] */ + .cif_wrdma_fs_delay = REG_FIELD_ID(0x15058, 8, 11, 4, 0x1000), /* FS_DELAY [11:8] */ + .cif_wrdma_active_ch_en = REG_FIELD_ID(0x15058, 12, 27, 4, 0x1000), + /* ACTIVE_CHANNEL_EN [27:12] */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG (0x4004 + 0x1000*a) */ + .aif_inv_sync = REG_FIELD_ID(0x4004, 12, 12, 4, 0x1000), /* bit 12 */ + .aif_sync_delay = REG_FIELD_ID(0x4004, 8, 9, 4, 0x1000), /* bits 9:8 */ + .aif_sync_mode = REG_FIELD_ID(0x4004, 4, 5, 4, 0x1000), /* bits 5:4 */ + .aif_sync_src = REG_FIELD_ID(0x4004, 0, 0, 4, 0x1000), /* bit 0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG (0x4008 + 0x1000*a) */ + .aif_sample_width_rx = REG_FIELD_ID(0x4008, 24, 28, 4, 0x1000), /* bits 28:24 */ + .aif_sample_width_tx = REG_FIELD_ID(0x4008, 16, 20, 4, 0x1000), /* bits 20:16 */ + .aif_slot_width_rx = REG_FIELD_ID(0x4008, 8, 12, 4, 0x1000), /* bits 12:8 */ + .aif_slot_width_tx = REG_FIELD_ID(0x4008, 0, 4, 4, 0x1000), /* bits 4:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG (0x400C + 0x1000*a) */ + .aif_bits_per_lane = REG_FIELD_ID(0x400C, 0, 9, 4, 0x1000), /* bits 9:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX (0x4010 + 0x1000*a) */ + .aif_slot_en_tx_mask = REG_FIELD_ID(0x4010, 0, 31, 4, 0x1000), /* bits 31:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX (0x4030 + 0x1000*a) */ + .aif_slot_en_rx_mask = REG_FIELD_ID(0x4030, 0, 31, 4, 0x1000), /* bits 31:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG (0x4050 + 0x1000*a) */ + .aif_loopback_en = REG_FIELD_ID(0x4050, 31, 31, 4, 0x1000), /* bit 31 */ + .aif_ctrl_data_oe = REG_FIELD_ID(0x4050, 16, 16, 4, 0x1000), /* bit 16 */ + .aif_lane_en = REG_FIELD_ID(0x4050, 8, 15, 4, 0x1000), /* bits 15:8 */ + .aif_lane_dir = REG_FIELD_ID(0x4050, 0, 7, 4, 0x1000), /* bits 7:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG (0x4054 + 0x1000*a) */ + .aif_mono_mode_rx = REG_FIELD_ID(0x4054, 1, 1, 4, 0x1000), /* bit 1 */ + .aif_mono_mode_tx = REG_FIELD_ID(0x4054, 0, 0, 4, 0x1000), /* bit 0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG (0x4058 + 0x1000*a) */ + .aif_full_cycle_en = REG_FIELD_ID(0x4058, 0, 0, 4, 0x1000), /* bit 0 */ + + .clk_name = (const char*[]) { + "gcc_lpass_config_clk", + "gcc_lpass_core_axim_clk", + "audio_core_cc_bus_clk" + }, + .num_clks = 3, + + .dai_driver = shikra_qaif_cpu_dai_driver, + .num_dai = ARRAY_SIZE(shikra_qaif_cpu_dai_driver), + /* Below Clocks should be mapped as per interface index */ + .dai_osr_clk_names = (const char *[]) { + "null" + }, + .dai_bit_clk_names = (const char *[]) { + "audio_core_cc_aif_if0_ibit_clk", /* if0 */ + "audio_core_cc_aif_if1_ibit_clk", /* if1 */ + "audio_core_cc_aif_if2_ibit_clk", /* if2 */ + "audio_core_cc_aif_if3_ibit_clk" /* if3 */ + }, + .init = shikra_qaif_init, + .exit = shikra_qaif_exit, + .alloc_stream_dma_idx = shikra_qaif_alloc_stream_dma_idx, + .free_stream_dma_idx = shikra_qaif_free_stream_dma_idx, + .get_dma_idx = shikra_qaif_get_dma_idx, +}; + +static const struct of_device_id shikra_qaif_cpu_device_id[] = { + {.compatible = "qcom,shikra-qaif-cpu", .data = &shikra_qaif_data}, + {} +}; +MODULE_DEVICE_TABLE(of, shikra_qaif_cpu_device_id); + +static struct platform_driver shikra_qaif_cpu_platform_driver = { + .driver = { + .name = "shikra-qaif-cpu", + .of_match_table = of_match_ptr(shikra_qaif_cpu_device_id), + .pm = &shikra_qaif_pm_ops, + }, + .probe = asoc_qcom_qaif_cpu_platform_probe, + .remove = asoc_qcom_qaif_cpu_platform_remove, + .shutdown = asoc_qcom_qaif_cpu_platform_shutdown, +}; +module_platform_driver(shikra_qaif_cpu_platform_driver); + +MODULE_DESCRIPTION("SHIKRA QAIF CPU DRIVER"); +MODULE_LICENSE("GPL"); From fa893ae7e16f8c509a8cc5b02b328533428c27d1 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 16 Apr 2026 09:46:07 +0530 Subject: [PATCH 0997/1058] ASoC: dt-bindings: qcom: Add Shikra rx and va macro codecs Add bindings for Qualcomm shikra rx and va macro codec. Signed-off-by: Mohammad Rafi Shaik --- Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml | 1 + Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 2eed2277511f8..07fe0dc51801b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -19,6 +19,7 @@ properties: - qcom,sm8450-lpass-rx-macro - qcom,sm8550-lpass-rx-macro - qcom,sc8280xp-lpass-rx-macro + - qcom,shikra-lpass-rx-macro - items: - enum: - qcom,kaanapali-lpass-rx-macro diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 5c42b2b323ee4..d43adaa2fbff9 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -19,6 +19,7 @@ properties: - qcom,sm8450-lpass-va-macro - qcom,sm8550-lpass-va-macro - qcom,sc8280xp-lpass-va-macro + - qcom,shikra-lpass-va-macro - items: - enum: - qcom,glymur-lpass-va-macro From 41b86d3d63334c495b59b89d42a519426eb9e208 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 11:00:15 +0530 Subject: [PATCH 0998/1058] ASoC: qcom: lpass-macro: Add LPASS codec v4.0 support for Shikra Shikra (QCM2290) carries a Bolero v4.0 LPASS codec that extends the existing VA and RX macro hardware in several ways. Wire up the new platform while keeping all changes strictly gated so that no existing platform is affected. VA macro changes: - Add LPASS_CODEC_VERSION_4_0 to the version enum and version-string helper in lpass-macro-common.h. - Introduce a dedicated shikra_va_data match-data struct that pre-sets codec version to 4.0 and marks bypass_fs_control, avoiding the need to read the version from hardware registers before clocks are up. - Add new register definitions for v4.0-only hardware blocks: * SWR GP-IN/GP-OUT channel registers (0x00E0-0x00FC) * Extended ADC MUX4-7 CFG0/1 (0x0120-0x013C) for 8-DMIC support * ADC MUXx CFG2 extension for all 8 muxes (0x0140-0x015C) * SWR INTR_CTRL registers (0x0340-0x03D0) * TX PATH CFG2 per decimator (0x0430/0x04B0/0x0530/0x05B0) * Adaptive filter blocks ADPT0-3 (0x0800-0x09A4) * ALT TOP configuration registers (0x1000-0x1140) - Split register defaults: common defaults stay in va_defaults[]; all v4.0-only defaults move to a new va_4_0_defaults[] array. The probe function builds the regmap config dynamically (mirroring rx-macro), merging va_4_0_defaults only for v4.0 and setting max_register to VA_MAX_OFFSET (0x1240) vs VA_MAX_OFFSET_PRE_4_0 (0x07A8) accordingly. - Guard va_is_rw_register() and va_is_volatile_register() so the new INTR_CTRL, MUX4-7, CFG2, TX_PATH_CFG2, ADPT, and ALT_TOP cases are only reachable when the codec version is 4.0. - Add bypass_fs_control bool to va_macro_data and va_macro structs. Gate the FS counter bit[7] toggle in va_clk_rsc_fs_gen_request() behind va->bypass_fs_control instead of a version comparison. - Add fsgen_gate_ops_4_0 clk_ops with recalc_rate (parent/2) used only for v4.0; the base fsgen_gate_ops is unchanged for all other platforms. - Fix a pre-existing bug where the TX1 and TX3 reg_default entries for TX_PATH_CFG2 incorrectly referenced CDC_VA_TX0_TX_PATH_CFG2 (0x0430) instead of their own addresses (0x04B0 and 0x05B0 respectively). RX macro changes: - Add LPASS_CODEC_VERSION_4_0 fall-through to the v2.5 register-set, control, widget, and probe stride/defaults selection paths, since the RX macro register layout is compatible with the 2.5 variant. - Add bypass_fs_control bool to rx_macro struct; set it from the new LPASS_MACRO_FLAG_BYPASS_FS_CONTROL flag in rx_macro_probe(). - Gate the FS counter bit[7] toggle in rx_macro_mclk_enable() behind rx->bypass_fs_control instead of a version comparison. - Add qcom,shikra-lpass-rx-macro DT match entry with both LPASS_MACRO_FLAG_HAS_NPL_CLOCK and LPASS_MACRO_FLAG_BYPASS_FS_CONTROL. Common header changes: - Add LPASS_MACRO_FLAG_BYPASS_FS_CONTROL BIT(2) to lpass-macro-common.h to signal that the FS counter control bit[7] must be toggled during mclk enable. This is a platform capability flag, not a version check, so it can be set independently of codec version in future platforms. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-macro-common.h | 5 + sound/soc/codecs/lpass-rx-macro.c | 14 + sound/soc/codecs/lpass-va-macro.c | 358 +++++++++++++++++++++++++- 3 files changed, 366 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 10ad682019fa7..0afcb2dce5d91 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -10,6 +10,8 @@ #define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) /* The soundwire block should be internally reset at probe */ #define LPASS_MACRO_FLAG_RESET_SWR BIT(1) +/* FS counter control bit[7] must be toggled (Shikra / v4.0) */ +#define LPASS_MACRO_FLAG_BYPASS_FS_CONTROL BIT(2) enum lpass_version { LPASS_VER_9_0_0, @@ -30,6 +32,7 @@ enum lpass_codec_version { LPASS_CODEC_VERSION_2_7, LPASS_CODEC_VERSION_2_8, LPASS_CODEC_VERSION_2_9, + LPASS_CODEC_VERSION_4_0, }; struct lpass_macro { @@ -68,6 +71,8 @@ static inline const char *lpass_macro_get_codec_version_string(int version) return "v2.7"; case LPASS_CODEC_VERSION_2_8: return "v2.8"; + case LPASS_CODEC_VERSION_4_0: + return "v4.0"; default: break; } diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 6233aa9f5bc6d..3a3dec6b14cda 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -646,6 +646,7 @@ struct rx_macro { int clsh_users; int rx_mclk_cnt; enum lpass_codec_version codec_version; + bool bypass_fs_control; int rxn_reg_stride; int rxn_reg_stride2; bool is_ear_mode_on; @@ -1612,6 +1613,7 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: return rx_2_5_is_rw_register(dev, reg); default: break; @@ -2043,6 +2045,11 @@ static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable) CDC_RX_CLK_MCLK2_ENABLE); regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00); + + if (rx->bypass_fs_control) + regmap_update_bits(regmap, + CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x80, 0x80); regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_EN_MASK, CDC_RX_FS_MCLK_CNT_ENABLE); @@ -3648,6 +3655,7 @@ static int rx_macro_component_probe(struct snd_soc_component *component) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: controls = rx_macro_2_5_snd_controls; num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); widgets = rx_macro_2_5_dapm_widgets; @@ -3809,6 +3817,7 @@ static int rx_macro_probe(struct platform_device *pdev) return PTR_ERR(base); rx->codec_version = lpass_macro_get_codec_version(); + rx->bypass_fs_control = !!(flags & LPASS_MACRO_FLAG_BYPASS_FS_CONTROL); struct reg_default *reg_defaults __free(kfree) = NULL; switch (rx->codec_version) { @@ -3831,6 +3840,7 @@ static int rx_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: rx->rxn_reg_stride = 0xc0; rx->rxn_reg_stride2 = 0x0; def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); @@ -3961,6 +3971,10 @@ static const struct of_device_id rx_macro_dt_match[] = { }, { .compatible = "qcom,sc8280xp-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,shikra-lpass-rx-macro", + .data = (void *)(LPASS_MACRO_FLAG_HAS_NPL_CLOCK | + LPASS_MACRO_FLAG_BYPASS_FS_CONTROL), }, { } }; diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 528d5b167ecff..0d4d94adf121c 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -81,6 +81,14 @@ #define CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK (0xEE) #define CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1 (0xCC) #define CDC_VA_TOP_CSR_SWR_CTRL (0x00DC) + +#define CDC_VA_TOP_CSR_SWR_GPIN_CH0 (0x00E0) +#define CDC_VA_TOP_CSR_SWR_GPIN_CH1 (0x00E4) +#define CDC_VA_TOP_CSR_TOP_CFG2 (0x00EC) +#define CDC_VA_TOP_CSR_TOP_CFG3 (0x00F0) +#define CDC_VA_TOP_CSR_SWR_GPOUT_CH0 (0x00F8) +#define CDC_VA_TOP_CSR_SWR_GPOUT_CH1 (0x00FC) + #define CDC_VA_INP_MUX_ADC_MUX0_CFG0 (0x0100) #define CDC_VA_INP_MUX_ADC_MUX0_CFG1 (0x0104) #define CDC_VA_INP_MUX_ADC_MUX1_CFG0 (0x0108) @@ -89,6 +97,40 @@ #define CDC_VA_INP_MUX_ADC_MUX2_CFG1 (0x0114) #define CDC_VA_INP_MUX_ADC_MUX3_CFG0 (0x0118) #define CDC_VA_INP_MUX_ADC_MUX3_CFG1 (0x011C) + +/* ADC MUX4-7 CFG0/1 - Bolero V4 extended decimator mux (up to 8 DMICs) */ +#define CDC_VA_INP_MUX_ADC_MUX4_CFG0 (0x0120) +#define CDC_VA_INP_MUX_ADC_MUX4_CFG1 (0x0124) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG0 (0x0128) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG1 (0x012C) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG0 (0x0130) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG1 (0x0134) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG0 (0x0138) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG1 (0x013C) + +/* ADC MUXx CFG2 - Bolero V4 CFG2 extension for all 8 MUXes */ +#define CDC_VA_INP_MUX_ADC_MUX0_CFG2 (0x0140) +#define CDC_VA_INP_MUX_ADC_MUX1_CFG2 (0x0144) +#define CDC_VA_INP_MUX_ADC_MUX2_CFG2 (0x0148) +#define CDC_VA_INP_MUX_ADC_MUX3_CFG2 (0x014C) +#define CDC_VA_INP_MUX_ADC_MUX4_CFG2 (0x0150) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG2 (0x0154) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG2 (0x0158) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG2 (0x015C) + +/* INTR_CTRL registers - SWR interrupt controller (VA macro owns SWR0 on QCM2290) */ +#define CDC_VA_MACRO_INTR_CTRL_CFG (0x0340) +#define CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT (0x0344) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0 (0x0360) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0 (0x0368) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0 (0x0370) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0 (0x0380) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0 (0x0388) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0 (0x0390) +#define CDC_VA_MACRO_INTR_CTRL_LEVEL0 (0x03C0) +#define CDC_VA_MACRO_INTR_CTRL_BYPASS0 (0x03C8) +#define CDC_VA_MACRO_INTR_CTRL_SET0 (0x03D0) + #define CDC_VA_TX0_TX_PATH_CTL (0x0400) #define CDC_VA_TX_PATH_CLK_EN_MASK BIT(5) #define CDC_VA_TX_PATH_CLK_EN BIT(5) @@ -118,6 +160,9 @@ #define CDC_VA_TX0_TX_PATH_SEC5 (0x0424) #define CDC_VA_TX0_TX_PATH_SEC6 (0x0428) #define CDC_VA_TX0_TX_PATH_SEC7 (0x042C) + +#define CDC_VA_TX0_TX_PATH_CFG2 (0x0430) + #define CDC_VA_TX1_TX_PATH_CTL (0x0480) #define CDC_VA_TX1_TX_PATH_CFG0 (0x0484) #define CDC_VA_TX1_TX_PATH_CFG1 (0x0488) @@ -129,6 +174,9 @@ #define CDC_VA_TX1_TX_PATH_SEC4 (0x04A0) #define CDC_VA_TX1_TX_PATH_SEC5 (0x04A4) #define CDC_VA_TX1_TX_PATH_SEC6 (0x04A8) + +#define CDC_VA_TX1_TX_PATH_CFG2 (0x04B0) + #define CDC_VA_TX2_TX_PATH_CTL (0x0500) #define CDC_VA_TX2_TX_PATH_CFG0 (0x0504) #define CDC_VA_TX2_TX_PATH_CFG1 (0x0508) @@ -140,6 +188,9 @@ #define CDC_VA_TX2_TX_PATH_SEC4 (0x0520) #define CDC_VA_TX2_TX_PATH_SEC5 (0x0524) #define CDC_VA_TX2_TX_PATH_SEC6 (0x0528) + +#define CDC_VA_TX2_TX_PATH_CFG2 (0x0530) + #define CDC_VA_TX3_TX_PATH_CTL (0x0580) #define CDC_VA_TX3_TX_PATH_CFG0 (0x0584) #define CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK BIT(7) @@ -155,7 +206,66 @@ #define CDC_VA_TX3_TX_PATH_SEC5 (0x05A4) #define CDC_VA_TX3_TX_PATH_SEC6 (0x05A8) -#define VA_MAX_OFFSET (0x07A8) +#define CDC_VA_TX3_TX_PATH_CFG2 (0x05B0) + +#define CDC_VA_CDC_ADPT0_ADPT_CTRL (0x0800) +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_0 (0x0804) +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_1 (0x0808) +#define CDC_VA_CDC_ADPT0_DH_FSM_CTRL (0x080C) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0 (0x0810) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1 (0x0814) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2 (0x0818) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3 (0x081C) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4 (0x0820) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5 (0x0824) + +#define CDC_VA_CDC_ADPT1_ADPT_CTRL (0x0880) +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_0 (0x0884) +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_1 (0x0888) +#define CDC_VA_CDC_ADPT1_DH_FSM_CTRL (0x088C) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0 (0x0890) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1 (0x0894) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2 (0x0898) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3 (0x089C) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4 (0x08A0) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5 (0x08A4) +#define CDC_VA_CDC_ADPT1_DBG_CTRL (0x08B0) +#define CDC_VA_CDC_ADPT1_DBG_PDM_RATE_CTRL_0 (0x08B2) +#define CDC_VA_CDC_ADPT1_DBG_PDM_RATE_CTRL_1 (0x08B4) +#define CDC_VA_CDC_ADPT1_SPARE0 (0x08B8) + +#define CDC_VA_CDC_ADPT2_ADPT_CTRL (0x0900) +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_0 (0x0904) +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_1 (0x0908) +#define CDC_VA_CDC_ADPT2_DH_FSM_CTRL (0x090C) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0 (0x0910) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1 (0x0914) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2 (0x0918) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3 (0x091C) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4 (0x0920) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5 (0x0924) + +#define CDC_VA_CDC_ADPT3_ADPT_CTRL (0x0980) +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_0 (0x0984) +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_1 (0x0988) +#define CDC_VA_CDC_ADPT3_DH_FSM_CTRL (0x098C) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0 (0x0990) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1 (0x0994) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2 (0x0998) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3 (0x099C) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4 (0x09A0) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5 (0x09A4) + +/* VA ALT TOP registers - Bolero V4 alternate top config */ +#define CDC_VA_ALT_TOP_VA_CFG0 0x1000 +#define CDC_VA_ALT_TOP_RX_CFG0 0x1040 +#define CDC_VA_ALT_TOP_WSA1_CFG0 0x1080 +#define CDC_VA_ALT_TOP_WSA2_CFG0 0x10C0 +#define CDC_VA_ALT_TOP_WSA3_CFG0 0x1100 +#define CDC_VA_ALT_TOP_WSA4_CFG0 0x1140 + +#define VA_MAX_OFFSET (0x1240) +#define VA_MAX_OFFSET_PRE_4_0 (0x07A8) #define VA_MACRO_NUM_DECIMATORS 4 #define VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ @@ -209,6 +319,8 @@ struct va_macro { u16 dmic_clk_div; bool has_swr_master; bool has_npl_clk; + bool bypass_fs_control; + enum lpass_codec_version codec_version; int dec_mode[VA_MACRO_NUM_DECIMATORS]; struct regmap *regmap; @@ -235,6 +347,7 @@ struct va_macro { struct va_macro_data { bool has_swr_master; bool has_npl_clk; + bool bypass_fs_control; int version; }; @@ -249,6 +362,13 @@ static const struct va_macro_data sm8450_va_data = { .has_npl_clk = true, }; +static const struct va_macro_data shikra_va_data = { + .has_swr_master = true, + .has_npl_clk = true, + .bypass_fs_control = true, + .version = LPASS_CODEC_VERSION_4_0, +}; + static const struct va_macro_data sm8550_va_data = { .has_swr_master = true, .has_npl_clk = false, @@ -266,7 +386,23 @@ static bool va_is_volatile_register(struct device *dev, unsigned int reg) case CDC_VA_TOP_CSR_DMIC2_CTL: case CDC_VA_TOP_CSR_DMIC3_CTL: return true; + default: + break; } + + if (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_0) { + switch (reg) { + case CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0: + case CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT: + return true; + default: + break; + } + } + return false; } @@ -304,6 +440,7 @@ static const struct reg_default va_defaults[] = { { CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, { CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, { CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { CDC_VA_TX0_TX_PATH_CTL, 0x04}, { CDC_VA_TX0_TX_PATH_CFG0, 0x10}, { CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, @@ -351,6 +488,101 @@ static const struct reg_default va_defaults[] = { { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, }; +/* Register defaults specific to LPASS codec v4.0 (Shikra) */ +static const struct reg_default va_4_0_defaults[] = { + /* ADC MUX4-7 CFG0/1 - 8-DMIC support */ + { CDC_VA_INP_MUX_ADC_MUX4_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX4_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG1, 0x00 }, + + /* ADC MUXx CFG2 extension */ + { CDC_VA_INP_MUX_ADC_MUX0_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX1_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX2_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX3_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX4_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG2, 0x00 }, + + /* INTR_CTRL: SWR interrupt masking registers */ + { CDC_VA_MACRO_INTR_CTRL_CFG, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0, 0xFF }, + { CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0, 0xFF }, + { CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_LEVEL0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_BYPASS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_SET0, 0x00 }, + + /* TX PATH CFG2 per decimator */ + { CDC_VA_TX0_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX1_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX2_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX3_TX_PATH_CFG2, 0x03 }, + + /* CDC ADPT0 - adaptive filter */ + { CDC_VA_CDC_ADPT0_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT0_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT1 */ + { CDC_VA_CDC_ADPT1_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT1_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT2 */ + { CDC_VA_CDC_ADPT2_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT2_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT3 */ + { CDC_VA_CDC_ADPT3_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT3_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* VA ALT TOP */ + { CDC_VA_ALT_TOP_VA_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_RX_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA1_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA2_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA3_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA4_CFG0, 0x00 }, +}; + static bool va_is_rw_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -425,6 +657,41 @@ static bool va_is_rw_register(struct device *dev, unsigned int reg) case CDC_VA_TX3_TX_PATH_SEC5: case CDC_VA_TX3_TX_PATH_SEC6: return true; + default: + break; + } + + if (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_0) { + switch (reg) { + case CDC_VA_MACRO_INTR_CTRL_CFG: + case CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT: + case CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0: + case CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_LEVEL0: + case CDC_VA_MACRO_INTR_CTRL_BYPASS0: + case CDC_VA_MACRO_INTR_CTRL_SET0: + case CDC_VA_INP_MUX_ADC_MUX4_CFG0 ... CDC_VA_INP_MUX_ADC_MUX7_CFG1: + case CDC_VA_INP_MUX_ADC_MUX0_CFG2 ... CDC_VA_INP_MUX_ADC_MUX7_CFG2: + case CDC_VA_TX0_TX_PATH_CFG2: + case CDC_VA_TX1_TX_PATH_CFG2: + case CDC_VA_TX2_TX_PATH_CFG2: + case CDC_VA_TX3_TX_PATH_CFG2: + case CDC_VA_ALT_TOP_VA_CFG0: + case CDC_VA_ALT_TOP_RX_CFG0: + case CDC_VA_ALT_TOP_WSA1_CFG0: + case CDC_VA_ALT_TOP_WSA2_CFG0: + case CDC_VA_ALT_TOP_WSA3_CFG0: + case CDC_VA_ALT_TOP_WSA4_CFG0: + case CDC_VA_CDC_ADPT0_ADPT_CTRL ... CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT1_ADPT_CTRL ... CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT2_ADPT_CTRL ... CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT3_ADPT_CTRL ... CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5: + return true; + default: + break; + } } return false; @@ -449,9 +716,6 @@ static const struct regmap_config va_regmap_config = { .val_bits = 32, .reg_stride = 4, .cache_type = REGCACHE_FLAT, - .reg_defaults = va_defaults, - .num_reg_defaults = ARRAY_SIZE(va_defaults), - .max_register = VA_MAX_OFFSET, .volatile_reg = va_is_volatile_register, .readable_reg = va_is_readable_register, .writeable_reg = va_is_rw_register, @@ -469,6 +733,10 @@ static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR); + + if (va->bypass_fs_control) + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x80, 0x80); regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN); @@ -1386,12 +1654,25 @@ static int fsgen_gate_is_enabled(struct clk_hw *hw) return !!(val & CDC_VA_FS_BROADCAST_EN); } +static unsigned long fsgen_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / 2; +} + static const struct clk_ops fsgen_gate_ops = { .prepare = fsgen_gate_enable, .unprepare = fsgen_gate_disable, .is_enabled = fsgen_gate_is_enabled, }; +static const struct clk_ops fsgen_gate_ops_4_0 = { + .prepare = fsgen_gate_enable, + .unprepare = fsgen_gate_disable, + .is_enabled = fsgen_gate_is_enabled, + .recalc_rate = fsgen_recalc_rate, +}; + static int va_macro_register_fsgen_output(struct va_macro *va) { struct clk *parent = va->mclk; @@ -1410,7 +1691,8 @@ static int va_macro_register_fsgen_output(struct va_macro *va) of_property_read_string(np, "clock-output-names", &clk_name); init.name = clk_name; - init.ops = &fsgen_gate_ops; + init.ops = (va->codec_version == LPASS_CODEC_VERSION_4_0) + ? &fsgen_gate_ops_4_0 : &fsgen_gate_ops; init.flags = 0; init.parent_names = &parent_clk_name; init.num_parents = 1; @@ -1511,6 +1793,14 @@ static int va_macro_set_lpass_codec_version(struct va_macro *va) default: break; } + } else if (maj == 4) { + switch (min) { + case 0: + version = LPASS_CODEC_VERSION_4_0; + break; + default: + break; + } } if (version == LPASS_CODEC_VERSION_UNKNOWN) { @@ -1520,6 +1810,7 @@ static int va_macro_set_lpass_codec_version(struct va_macro *va) } lpass_macro_set_codec_version(version); + va->codec_version = version; dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version)); @@ -1576,18 +1867,61 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - va->regmap = devm_regmap_init_mmio(dev, base, &va_regmap_config); + data = of_device_get_match_data(dev); + va->has_swr_master = data->has_swr_master; + va->has_npl_clk = data->has_npl_clk; + va->bypass_fs_control = data->bypass_fs_control; + + /* + * Use the version from match data if available; for platforms that + * detect version from registers, clocks must be enabled first, so + * the full detection is deferred to after clk_prepare_enable below. + */ + va->codec_version = data->version ? data->version : LPASS_CODEC_VERSION_UNKNOWN; + + int def_count; + struct reg_default *reg_defaults_buf __free(kfree) = NULL; + + if (va->codec_version == LPASS_CODEC_VERSION_4_0) { + def_count = ARRAY_SIZE(va_defaults) + ARRAY_SIZE(va_4_0_defaults); + reg_defaults_buf = kmalloc_objs(struct reg_default, def_count); + if (!reg_defaults_buf) { + ret = -ENOMEM; + goto err; + } + memcpy(®_defaults_buf[0], va_defaults, sizeof(va_defaults)); + memcpy(®_defaults_buf[ARRAY_SIZE(va_defaults)], + va_4_0_defaults, sizeof(va_4_0_defaults)); + } else { + def_count = ARRAY_SIZE(va_defaults); + reg_defaults_buf = kmalloc_objs(struct reg_default, def_count); + if (!reg_defaults_buf) { + ret = -ENOMEM; + goto err; + } + memcpy(reg_defaults_buf, va_defaults, sizeof(va_defaults)); + } + + struct regmap_config *reg_config __free(kfree) = + kmemdup(&va_regmap_config, sizeof(va_regmap_config), GFP_KERNEL); + if (!reg_config) { + ret = -ENOMEM; + goto err; + } + + reg_config->reg_defaults = reg_defaults_buf; + reg_config->num_reg_defaults = def_count; + reg_config->max_register = (va->codec_version == LPASS_CODEC_VERSION_4_0) + ? VA_MAX_OFFSET : VA_MAX_OFFSET_PRE_4_0; + + va->regmap = devm_regmap_init_mmio(dev, base, reg_config); if (IS_ERR(va->regmap)) { - ret = -EINVAL; + ret = PTR_ERR(va->regmap); goto err; } dev_set_drvdata(dev, va); - data = of_device_get_match_data(dev); - va->has_swr_master = data->has_swr_master; - va->has_npl_clk = data->has_npl_clk; - /* mclk rate */ clk_set_rate(va->mclk, 2 * VA_MACRO_MCLK_FREQ); @@ -1625,6 +1959,7 @@ static int va_macro_probe(struct platform_device *pdev) */ if (data->version) { lpass_macro_set_codec_version(data->version); + va->codec_version = data->version; } else { /* read version from register */ ret = va_macro_set_lpass_codec_version(va); @@ -1761,6 +2096,7 @@ static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data }, { .compatible = "qcom,sm8550-lpass-va-macro", .data = &sm8550_va_data }, { .compatible = "qcom,sc8280xp-lpass-va-macro", .data = &sm8450_va_data }, + { .compatible = "qcom,shikra-lpass-va-macro", .data = &shikra_va_data }, {} }; MODULE_DEVICE_TABLE(of, va_macro_dt_match); From 23bfb3fe5e307253f778cdd4025957f53bb41c58 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 11:20:37 +0530 Subject: [PATCH 0999/1058] dt-bindings: soundwire: qcom: add qcom,swr-master-ee-val property Add documentation for the qcom,swr-master-ee-val Device Tree property used by Qualcomm SoundWire masters to describe the execution-environment value for interrupt routing. This property allows platform DTs to specify the EE value used to direct SoundWire master interrupts to the appropriate CPU target. Signed-off-by: Mohammad Rafi Shaik --- .../devicetree/bindings/soundwire/qcom,soundwire.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml index 9447a2f371b56..5b06cc1a5f781 100644 --- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml +++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml @@ -215,6 +215,12 @@ properties: maximum: 4 - const: 0xff + qcom,swr-master-ee-val: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: + Execution-environment value used to route SoundWire master + interrupts to CPU0 or CPU1. + label: maxItems: 1 From a4a82df88a501af58e5fbb93fc2b27c7dac98d23 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 11:30:31 +0530 Subject: [PATCH 1000/1058] soundwire: qcom: add EE-aware register layout and cpu selection Some Qualcomm SoundWire masters expose interrupt, FIFO and status registers in EE-specific register windows on v2.0 and newer hardware. Add support for selecting the SoundWire execution environment from DT and use it to program the correct register window for the active EE. The driver now reads the EE value from the new qcom,swr-master-ee-val property, with qcom,ee as a fallback for backward compatibility. For v2.0+ hardware, the IRQ/FIFO/status register layout is adjusted by the EE window stride so the driver programs the correct bank for the selected EE. The interrupt enable path is also updated to always use the selected EE window. This change allows SoundWire interrupt routing and register accesses to work correctly on platforms where the master is not mapped to the default EE1 window. Signed-off-by: Mohammad Rafi Shaik --- drivers/soundwire/qcom.c | 103 +++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 3d8f5a81eff19..5ad8aaaa3de44 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -26,6 +26,7 @@ #define SWRM_COMP_STATUS 0x014 #define SWRM_LINK_MANAGER_EE 0x018 #define SWRM_EE_CPU 1 +#define SWRM_MAX_EE 1 #define SWRM_FRM_GEN_ENABLED BIT(0) #define SWRM_VERSION_1_3_0 0x01030000 #define SWRM_VERSION_1_5_1 0x01050001 @@ -118,6 +119,7 @@ #define SWRM_V2_0_CLK_CTRL 0x5060 #define SWRM_V2_0_CLK_CTRL_CLK_START BIT(0) #define SWRM_V2_0_LINK_STATUS 0x5064 +#define SWRM_V2_REG_EE_STRIDE 0x1000 #define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 @@ -202,6 +204,7 @@ struct qcom_swrm_ctrl { struct mutex port_lock; struct clk *hclk; int irq; + u32 ee; unsigned int version; int wake_irq; int num_din_ports; @@ -222,6 +225,7 @@ struct qcom_swrm_ctrl { u32 slave_status; u32 wr_fifo_depth; bool clock_stop_not_supported; + unsigned int reg_layout_local[SWRM_OFFSET_DP_SAMPLECTRL2_BANK + 1]; }; struct qcom_swrm_data { @@ -328,6 +332,36 @@ static const struct qcom_swrm_data swrm_v3_0_data = { }; #define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus) +static void qcom_swrm_set_ee_register_layout(struct qcom_swrm_ctrl *ctrl, + const struct qcom_swrm_data *data) +{ + int ee_offset; + + memcpy(ctrl->reg_layout_local, data->reg_layout, + sizeof(ctrl->reg_layout_local)); + ctrl->reg_layout = ctrl->reg_layout_local; + + if (ctrl->version < SWRM_VERSION_2_0_0) + return; + + /* + * Current register constants map EE1. For EE0, use the EE register + * window stride to access status/IRQ/FIFO registers. + */ + ee_offset = ((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE; + if (!ee_offset) + return; + + ctrl->reg_layout_local[SWRM_REG_FRAME_GEN_ENABLED] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_STATUS] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CLEAR] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CPU_EN] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_WR_CMD] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_CMD] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_STATUS] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] += ee_offset; +} + static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val) { @@ -904,12 +938,13 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val); if (ctrl->version == SWRM_VERSION_1_7_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, - SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); + SWRM_MCP_BUS_CLK_START << ctrl->ee); } else if (ctrl->version >= SWRM_VERSION_2_0_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL + + ((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE, SWRM_V2_0_CLK_CTRL_CLK_START); } else { ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); @@ -935,11 +970,9 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], 0xFFFFFFFF); - /* enable CPU IRQs */ - if (ctrl->mmio) { - ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], - SWRM_INTERRUPT_STATUS_RMSK); - } + /* enable CPU IRQs for the selected EE window */ + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + SWRM_INTERRUPT_STATUS_RMSK); /* Set IRQ to PULSE */ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, @@ -1545,7 +1578,22 @@ static int qcom_swrm_probe(struct platform_device *pdev) return -ENOMEM; data = of_device_get_match_data(dev); + ctrl->ee = SWRM_EE_CPU; + ret = of_property_read_u32(dev->of_node, "qcom,swr-master-ee-val", &ctrl->ee); + if (ret) + ret = of_property_read_u32(dev->of_node, "qcom,ee", &ctrl->ee); + if (ret) + ctrl->ee = SWRM_EE_CPU; + if (ctrl->ee > SWRM_MAX_EE) { + dev_warn(dev, "invalid SoundWire EE %u, using EE%u\n", + ctrl->ee, SWRM_EE_CPU); + ctrl->ee = SWRM_EE_CPU; + } ctrl->max_reg = data->max_reg; + /* + * Defer EE register window selection until HW version is known. + * For v2.0+ the IRQ/FIFO window is EE-banked. + */ ctrl->reg_layout = data->reg_layout; ctrl->rows_index = sdw_find_row_index(data->default_rows); ctrl->cols_index = sdw_find_col_index(data->default_cols); @@ -1623,6 +1671,7 @@ static int qcom_swrm_probe(struct platform_device *pdev) prop->default_row = data->default_rows; ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &ctrl->version); + qcom_swrm_set_ee_register_layout(ctrl, data); ret = devm_request_threaded_irq(dev, ctrl->irq, NULL, qcom_swrm_irq_handler, @@ -1724,24 +1773,26 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev) if (!swrm_wait_for_frame_gen_enabled(ctrl)) dev_err(ctrl->dev, "link failed to connect\n"); - /* wait for hw enumeration to complete */ - wait_for_completion_timeout(&ctrl->enumeration, - msecs_to_jiffies(TIMEOUT_MS)); - qcom_swrm_get_device_status(ctrl); - sdw_handle_slave_status(&ctrl->bus, ctrl->status); - } else { - reset_control_reset(ctrl->audio_cgcr); - - if (ctrl->version == SWRM_VERSION_1_7_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, - SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); - } else if (ctrl->version >= SWRM_VERSION_2_0_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, - SWRM_V2_0_CLK_CTRL_CLK_START); + /* wait for hw enumeration to complete */ + wait_for_completion_timeout(&ctrl->enumeration, + msecs_to_jiffies(TIMEOUT_MS)); + qcom_swrm_get_device_status(ctrl); + sdw_handle_slave_status(&ctrl->bus, ctrl->status); } else { - ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); + reset_control_reset(ctrl->audio_cgcr); + + if (ctrl->version == SWRM_VERSION_1_7_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, + SWRM_MCP_BUS_CLK_START << ctrl->ee); + } else if (ctrl->version >= SWRM_VERSION_2_0_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL + + ((int)ctrl->ee - SWRM_EE_CPU) * + SWRM_V2_REG_EE_STRIDE, + SWRM_V2_0_CLK_CTRL_CLK_START); + } else { + ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); } ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET); From 455e3be91d3ac0881e5527f07d93c44b0356f066 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 11 May 2026 12:22:04 +0530 Subject: [PATCH 1001/1058] ASoC: dt-bindings: qcom,sm8250: Add shikra sound card Add bindings for shikra sound card, which looks fully compatible with existing shikra. Signed-off-by: Mohammad Rafi Shaik --- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 15f38622b98b9..1c6fd7798de0d 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -45,6 +45,7 @@ properties: - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard - qcom,sdm845-sndcard + - qcom,shikra-sndcard - qcom,sm8250-sndcard - qcom,sm8450-sndcard - qcom,x1e80100-sndcard From e7945959efd73c7b0d148f8d639c3da0034ba5f9 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 11 May 2026 12:23:13 +0530 Subject: [PATCH 1002/1058] ASoC: qcom: sc8280xp: Add support for shikra Add compatible for sound card on Qualcomm shikra boards. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 7925aa3f63ba0..b59d6e506e405 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -172,6 +172,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { {.compatible = "qcom,qcs9075-sndcard", "sa8775p"}, {.compatible = "qcom,qcs9100-sndcard", "sa8775p"}, {.compatible = "qcom,sc8280xp-sndcard", "sc8280xp"}, + {.compatible = "qcom,shikra-sndcard", "shikra"}, {.compatible = "qcom,sm8450-sndcard", "sm8450"}, {.compatible = "qcom,sm8550-sndcard", "sm8550"}, {.compatible = "qcom,sm8650-sndcard", "sm8650"}, From cd2c5bd6a5be4e45eca12417f0b08d6134637369 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 26 May 2026 12:51:51 +0530 Subject: [PATCH 1003/1058] ASoC: codecs: wsa885x-i2c: make TDM control sequence slot-aware Pass the requested TDM slot count into reg_update_sequence() and program DIG_CTRL1_I2S_TDM_CTL0 based on 2-, 4-, or 8-slot modes. This allows the WSA885x I2C codec driver to configure TDM control registers correctly for different slot configurations instead of using a fixed value. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/wsa885x-i2c.c | 118 +++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wsa885x-i2c.c b/sound/soc/codecs/wsa885x-i2c.c index 2ace3a0956b25..1d40761106177 100644 --- a/sound/soc/codecs/wsa885x-i2c.c +++ b/sound/soc/codecs/wsa885x-i2c.c @@ -196,6 +196,11 @@ #define FU21_VOL_STEPS 124 static const DECLARE_TLV_DB_SCALE(fu21_digital_gain, -8400, 100, 0); +/*TDM Slots*/ +#define WSA885X_TDM8 0X08 +#define WSA885X_TDM4 0X04 +#define WSA885X_TDM2 0X02 + static const char *const supply_name[] = { "vdd-io", "vdd-1p8", @@ -408,13 +413,21 @@ static int wsa885x_gpio_set(struct wsa885x_i2c_priv *wsa885x, bool val) return ret; } -static void reg_update_sequence(struct regmap *regmap) +static void reg_update_sequence(struct regmap *regmap, int slots) { regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x15); regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x11); /* Configure TDM control register 0 */ - regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x04); + if (slots == WSA885X_TDM2) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x0); + else if (slots == WSA885X_TDM4) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x04); + else if (slots == WSA885X_TDM8) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0xC); + else + pr_warn("Invalid TDM slot count: %d, expected 2, 4, or 8\n", slots); + regmap_update_bits(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x01, 0x01); /* Configure TDM transmit channel settings */ @@ -616,7 +629,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai, regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, 0x60, 0x60); /* Apply TDM control sequence */ - reg_update_sequence(wsa885x->regmap); + reg_update_sequence(wsa885x->regmap, slots); /* Enable transmit channels */ regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x04, 0x04); @@ -630,7 +643,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai, /* Configure slot1 for current protection sense 0 */ regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, 0x50, 0x50); - reg_update_sequence(wsa885x->regmap); + reg_update_sequence(wsa885x->regmap, slots); } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_RIGHT) { /* Mono right channel configuration */ /* Configure slot0 for I-sense channel 1 */ @@ -639,7 +652,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai, /* Configure slot1 for current protection sense 1 */ regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, 0x60, 0x60); - reg_update_sequence(wsa885x->regmap); + reg_update_sequence(wsa885x->regmap, slots); } /* Enable I2S control */ @@ -719,6 +732,93 @@ static int codec_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } +static int wsa885x_handle_ssr_reset(struct wsa885x_i2c_priv *wsa885x) +{ + int ret; + + /* + * Re-toggle shutdown GPIO to force codec out of a potential SSR/fault + * state, then keep PA FSM disabled until power-up reconfiguration. + */ + if (wsa885x->sd_n) { + dev_dbg(wsa885x->component->dev, "%s: asserting powerdown gpio\n", + __func__); + ret = wsa885x_gpio_set(wsa885x, true); + if (ret) { + dev_err(wsa885x->component->dev, + "%s: failed to assert powerdown gpio: %d\n", + __func__, ret); + return ret; + } + + usleep_range(1000, 1500); + + dev_dbg(wsa885x->component->dev, "%s: deasserting powerdown gpio\n", + __func__); + ret = wsa885x_gpio_set(wsa885x, false); + if (ret) { + dev_err(wsa885x->component->dev, + "%s: failed to deassert powerdown gpio: %d\n", + __func__, ret); + return ret; + } + + usleep_range(2000, 2500); + } else { + dev_dbg(wsa885x->component->dev, + "%s: no powerdown gpio, skip gpio reset sequence\n", __func__); + } + + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + dev_dbg(wsa885x->component->dev, "%s: PA FSM disabled\n", __func__); + return 0; +} + +static int reinit_wsa885x_powerup(struct wsa885x_i2c_priv *wsa885x) +{ + int ret = 0; + int ps = 0; + + ret = wsa885x_handle_ssr_reset(wsa885x); + if (ret) { + dev_err(wsa885x->component->dev, "SSR reset failed: %d\n", ret); + return ret; + } + + dev_dbg(wsa885x->component->dev, "%s: programming reinit sequence\n", + __func__); + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_OT23_USAGE, + wsa885x->usage_mode); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01); + + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, + wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, + wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + dev_dbg(wsa885x->component->dev, + "%s: committed usage=%u vol_db=%d cluster=1 posture=1\n", + __func__, wsa885x->usage_mode, wsa885x->stereo_voldB); + + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x00); + dev_dbg(wsa885x->component->dev, "%s: requested PS%d\n", __func__, ps); + + ret = wait_for_pde_state(wsa885x, ps, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps); + } else { + dev_err(wsa885x->component->dev, + "Failed transitioned to power state %d\n", ps); + } + + return ret; +} + static int codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) { struct wsa885x_i2c_priv *wsa885x = snd_soc_dai_get_drvdata(dai); @@ -771,7 +871,9 @@ static int codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) "Successfully transitioned to power state %d\n", ps0); } else { dev_err(wsa885x->component->dev, "PS0 request failed\n"); - goto exit; + ret = reinit_wsa885x_powerup(wsa885x); + if (ret) + goto exit; } /* Configure power amplifier based on channel configuration */ @@ -1047,7 +1149,7 @@ static const struct snd_kcontrol_new wsa885x_snd_controls[] = { wsa885x_stereo_gain_offset_put, fu21_digital_gain), - SOC_SINGLE_EXT("Rx Slot Mask", SND_SOC_NOPM, 0, 4, 0, + SOC_SINGLE_EXT("Rx Slot Mask", SND_SOC_NOPM, 0, 3, 0, wsa885x_i2c_rx_slot_mask_get, wsa885x_i2c_rx_slot_mask_put), }; @@ -1337,6 +1439,8 @@ static const struct of_device_id wsa885x_i2c_dt_match[] = { }, {}}; +MODULE_DEVICE_TABLE(of, wsa885x_i2c_dt_match); + static const struct i2c_device_id wsa885x_id_i2c[] = { {"wsa885x_i2c", 0}, {} From 8c3ab8f5dc6468d0cec0309babf3c815adc24d42 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 28 May 2026 01:24:41 +0530 Subject: [PATCH 1004/1058] ASoC: qcom: sc8280xp: Fix the sc8280xp driver to support Shikra cqm and cqs Fix the sc8280xp driver to support Shikra cqm and cqs boards. Signed-off-by: Mohammad Rafi Shaik --- include/dt-bindings/sound/qcom,lpass.h | 2 ++ sound/soc/qcom/common.c | 2 ++ sound/soc/qcom/sc8280xp.c | 4 +++- sound/soc/qcom/sdw.c | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/sound/qcom,lpass.h b/include/dt-bindings/sound/qcom,lpass.h index a9404c3b8884c..e2c29416e2b98 100644 --- a/include/dt-bindings/sound/qcom,lpass.h +++ b/include/dt-bindings/sound/qcom,lpass.h @@ -41,6 +41,8 @@ #define LPASS_CDC_DMA_VA_TX7 32 #define LPASS_CDC_DMA_VA_TX8 33 +#define MI2S_SENARY 34 + #define LPASS_MCLK0 0 #endif /* __DT_QCOM_LPASS_H */ diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index edc4611691f73..2429c086673c8 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -2,6 +2,7 @@ // Copyright (c) 2018, Linaro Limited. // Copyright (c) 2018, The Linux Foundation. All rights reserved. +#include #include #include #include @@ -219,6 +220,7 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case LPASS_CDC_DMA_VA_TX1: for_each_rtd_codec_dais(rtd, i, codec_dai) { rval = snd_soc_component_set_jack(codec_dai->component, jack, NULL); diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index b59d6e506e405..f8a5bdac892bd 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022, Linaro Limited +#include #include #include #include @@ -86,6 +87,7 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case LPASS_CDC_DMA_VA_TX1: channels->min = 1; break; default: @@ -127,7 +129,7 @@ static void sc8280xp_add_be_ops(struct snd_soc_card *card) int i; for_each_card_prelinks(card, i, link) { - if (link->no_pcm == 1) { + if (link->no_pcm == 1 || link->num_codecs > 0) { link->init = sc8280xp_snd_init; link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup; link->ops = &sc8280xp_be_ops; diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 6576b47a4c8c3..cf70ffec71c17 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -41,6 +41,7 @@ static bool qcom_snd_is_sdw_dai(int id) switch (id) { case LPASS_CDC_DMA_TX3: case LPASS_CDC_DMA_RX0: + case LPASS_CDC_DMA_VA_TX1: return true; default: break; From 424f460bfd7a40afaca97cf19d870be4fdd9a058 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 27 May 2026 23:05:34 +0530 Subject: [PATCH 1005/1058] ASoC: codecs: lpass-va-macro: Add soundwire mic support Add soundwire Amic support on VA macro. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-va-macro.c | 78 ++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 0d4d94adf121c..22a4ab0f89c80 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -310,6 +310,11 @@ enum { VA_MACRO_CLK_DIV_16, }; +enum { + MSM_DMIC, + SWR_MIC, +}; + #define VA_NUM_CLKS_MAX 3 struct va_macro { @@ -820,14 +825,32 @@ static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, return -EINVAL; } - if (val != 0) - snd_soc_component_update_bits(component, mic_sel_reg, - CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, - CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + if (val != 0) { + if (strnstr(widget->name, "SMIC", strlen(widget->name))) + snd_soc_component_update_bits(component, mic_sel_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, 0); + else + snd_soc_component_update_bits(component, mic_sel_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, + CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + } return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); } +static bool is_amic_enabled(struct snd_soc_component *comp, int decimator) +{ + u16 adc_mux_reg = 0; + bool ret = false; + + adc_mux_reg = CDC_VA_INP_MUX_ADC_MUX0_CFG1 + + VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + if (snd_soc_component_read(comp, adc_mux_reg) & SWR_MIC) + return true; + + return ret; +} + static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1012,6 +1035,8 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; u16 tx_gain_ctl_reg; u8 hpf_cut_off_freq; + u16 adc_mux0_reg = 0; + u16 adapt_ctrl = 0; struct va_macro *va = snd_soc_component_get_drvdata(comp); @@ -1025,6 +1050,10 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, VA_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = CDC_VA_TX0_TX_VOL_CTL + VA_MACRO_TX_PATH_OFFSET * decimator; + adc_mux0_reg = CDC_VA_INP_MUX_ADC_MUX0_CFG0 + + VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + adapt_ctrl = CDC_VA_CDC_ADPT0_ADPT_CTRL + + VA_MACRO_TX_PATH_OFFSET *decimator; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1034,6 +1063,9 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, /* Enable TX PGA Mute */ break; case SND_SOC_DAPM_POST_PMU: + if (va->codec_version == LPASS_CODEC_VERSION_4_0) + snd_soc_component_update_bits(comp, adapt_ctrl, 0xFF, 0x00); + /* Enable TX CLK */ snd_soc_component_update_bits(comp, tx_vol_ctl_reg, CDC_VA_TX_PATH_CLK_EN_MASK, @@ -1042,7 +1074,13 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, CDC_VA_TX_HPF_ZERO_GATE_MASK, CDC_VA_TX_HPF_ZERO_GATE); - usleep_range(1000, 1010); + if (!is_amic_enabled(comp, decimator)) { + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_ZERO_GATE_MASK, + CDC_VA_TX_HPF_ZERO_GATE); + usleep_range(1000, 1010); + } + hpf_cut_off_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; @@ -1050,23 +1088,25 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, CF_MIN_3DB_150HZ << 5); + } - snd_soc_component_update_bits(comp, hpf_gate_reg, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); - /* - * Minimum 1 clk cycle delay is required as per HW spec - */ - usleep_range(1000, 1010); + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + + if (!is_amic_enabled(comp, decimator)) { snd_soc_component_update_bits(comp, - hpf_gate_reg, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, - 0x0); + hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + 0x0); } - usleep_range(1000, 1010); snd_soc_component_update_bits(comp, hpf_gate_reg, CDC_VA_TX_HPF_ZERO_GATE_MASK, @@ -1545,6 +1585,12 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + /* SWR_MIC routes: connect each VA DECx MUX to its SWR_MIC input */ + {"VA DEC0 MUX", "SWR_MIC", "VA SWR_MIC0"}, + {"VA DEC1 MUX", "SWR_MIC", "VA SWR_MIC1"}, + {"VA DEC2 MUX", "SWR_MIC", "VA SWR_MIC2"}, + {"VA DEC3 MUX", "SWR_MIC", "VA SWR_MIC3"}, + { "VA DMIC0", NULL, "DMIC0 Pin" }, { "VA DMIC1", NULL, "DMIC1 Pin" }, { "VA DMIC2", NULL, "DMIC2 Pin" }, From a985f509e5ccddbcf324eedbf7e268c9f32c4469 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 9 Mar 2026 16:42:57 +0530 Subject: [PATCH 1006/1058] ASoC: dt-bindings: qcom,q6apm-lpass-dais: Document DAI subnode Extend the qcom,q6apm-lpass-dais device tree binding to explicitly describe Digital Audio Interface (DAI) child nodes. Add #address-cells and #size-cells to allow representation of multiple DAI instances as child nodes, and define a dai@ pattern to document per-DAI properties such as the interface ID and associated clocks. Qualcomm platforms like talos integrate third-party audio codecs or use different external audio paths. These designs often require additional configuration such as explicit MI2S MCLK settings for audio to work. Co-developed-by: Srinivas Kandagatla Signed-off-by: Srinivas Kandagatla Signed-off-by: Mohammad Rafi Shaik --- .../bindings/sound/qcom,q6apm-lpass-dais.yaml | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml index 2fb95544db8b5..1d770cbcb058a 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml @@ -21,6 +21,34 @@ properties: '#sound-dai-cells': const: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +# Digital Audio Interfaces +patternProperties: + '^dai@[0-9]+$': + type: object + description: + Q6DSP Digital Audio Interfaces. + + properties: + reg: + description: + Digital Audio Interface ID + + clocks: + minItems: 1 + maxItems: 3 + + clock-names: + minItems: 1 + maxItems: 3 + + additionalProperties: false + required: - compatible - '#sound-dai-cells' @@ -29,7 +57,18 @@ unevaluatedProperties: false examples: - | - dais { + #include + + bedais { compatible = "qcom,q6apm-lpass-dais"; #sound-dai-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + dai@16 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; + }; }; From 934ee5a2c4f08f0613359df2aafdba31d40956c8 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 9 Mar 2026 16:42:58 +0530 Subject: [PATCH 1007/1058] ASoC: qcom: qdsp6: q6prm: add the missing LPASS MCLK clock IDs Add the missing LPASS MCLK ids for the q6prm ADSP. Co-developed-by: Srinivas Kandagatla Signed-off-by: Srinivas Kandagatla Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/qdsp6/q6prm-clocks.c | 5 +++++ sound/soc/qcom/qdsp6/q6prm.h | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/qcom/qdsp6/q6prm-clocks.c b/sound/soc/qcom/qdsp6/q6prm-clocks.c index 4c574b48ab004..51b131fa95316 100644 --- a/sound/soc/qcom/qdsp6/q6prm-clocks.c +++ b/sound/soc/qcom/qdsp6/q6prm-clocks.c @@ -42,6 +42,11 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_1), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_2), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_3), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_4), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_5), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), Q6PRM_CLK(LPASS_CLK_ID_VA_CORE_MCLK), diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/q6prm.h index a988a32086fe1..8296370e3cbf7 100644 --- a/sound/soc/qcom/qdsp6/q6prm.h +++ b/sound/soc/qcom/qdsp6/q6prm.h @@ -52,6 +52,17 @@ /* Clock ID for QUINARY MI2S OSR CLK */ #define Q6PRM_LPASS_CLK_ID_QUI_MI2S_OSR 0x116 +/* Clock ID for MCLK1 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_1 0x300 +/* Clock ID for MCLK2 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_2 0x301 +/* Clock ID for MCLK3 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_3 0x302 +/* Clock ID for MCLK4 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_4 0x303 +/* Clock ID for MCLK5 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_5 0x304 + #define Q6PRM_LPASS_CLK_ID_WSA_CORE_MCLK 0x305 #define Q6PRM_LPASS_CLK_ID_WSA_CORE_NPL_MCLK 0x306 From 529c4aa0547ff1fcfb46de22f585d17f009acf66 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 9 Mar 2026 16:42:59 +0530 Subject: [PATCH 1008/1058] ASoC: qcom: q6apm-lpass-dais: Add MI2S clock control Add support for MI2S clock control within q6apm-lpass DAIs, including handling of MCLK, BCLK, and ECLK via the DAI .set_sysclk callback. Each MI2S port now retrieves its clock handles from the device tree, allowing per-port clock configuration and proper enable/disable during startup and shutdown. Co-developed-by: Srinivas Kandagatla Signed-off-by: Srinivas Kandagatla Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 186 +++++++++++++++++++----- sound/soc/qcom/qdsp6/q6prm.h | 4 + 2 files changed, 155 insertions(+), 35 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 006b283484d9e..1e739a474936c 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -2,10 +2,12 @@ // Copyright (c) 2021, Linaro Limited #include +#include #include #include #include #include +#include #include #include #include @@ -15,13 +17,22 @@ #include "q6dsp-common.h" #include "audioreach.h" #include "q6apm.h" +#include "q6prm.h" #define AUDIOREACH_BE_PCM_BASE 16 +struct q6apm_dai_priv_data { + struct clk *mclk; + struct clk *bclk; + struct clk *eclk; + bool mclk_enabled, bclk_enabled, eclk_enabled; +}; + struct q6apm_lpass_dai_data { struct q6apm_graph *graph[APM_PORT_MAX]; bool is_port_started[APM_PORT_MAX]; struct audioreach_module_config module_config[APM_PORT_MAX]; + struct q6apm_dai_priv_data priv[APM_PORT_MAX]; }; static int q6dma_set_channel_map(struct snd_soc_dai *dai, @@ -150,7 +161,7 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct rc = q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; if (rc < 0) - dev_err(dai->dev, "failed to stop APM port (%d)\n", rc); + dev_err(dai->dev, "fail to close APM port (%d)\n", rc); } if (dai_data->graph[dai->id]) { @@ -159,31 +170,6 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct } } -static int q6apm_lpass_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!dai_data->is_port_started[dai->id]) { - ret = q6apm_graph_start(dai_data->graph[dai->id]); - if (ret < 0) - dev_err(dai->dev, "Failed to start APM port %d\n", dai->id); - else - dai_data->is_port_started[dai->id] = true; - } - break; - default: - break; - } - - return ret; -} - static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); @@ -196,14 +182,18 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + q6apm_graph_close(dai_data->graph[dai->id]); + dai_data->graph[dai->id] = NULL; + } } /** * It is recommend to load DSP with source graph first and then sink * graph, so sequence for playback and capture will be different */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) { - graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id); if (IS_ERR(graph)) { dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id); rc = PTR_ERR(graph); @@ -224,6 +214,14 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s dev_err(dai->dev, "Failed to prepare Graph %d\n", rc); goto err; } + + rc = q6apm_graph_start(dai_data->graph[dai->id]); + if (rc < 0) { + dev_err(dai->dev, "Failed to start APM port %d\n", dai->id); + goto err; + } + dai_data->is_port_started[dai->id] = true; + return 0; err: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -240,7 +238,7 @@ static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct s int graph_id = dai->id; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream); + graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id); if (IS_ERR(graph)) { dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id); return PTR_ERR(graph); @@ -251,6 +249,70 @@ static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct s return 0; } +static int q6i2s_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + return q6apm_lpass_dai_startup(substream, dai); +} + +static void q6i2s_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + + if (dai_data->priv[dai->id].mclk_enabled) { + clk_disable_unprepare(dai_data->priv[dai->id].mclk); + dai_data->priv[dai->id].mclk_enabled = false; + } + + if (dai_data->priv[dai->id].bclk_enabled) { + clk_disable_unprepare(dai_data->priv[dai->id].bclk); + dai_data->priv[dai->id].bclk_enabled = false; + } + + if (dai_data->priv[dai->id].eclk_enabled) { + clk_disable_unprepare(dai_data->priv[dai->id].eclk); + dai_data->priv[dai->id].eclk_enabled = false; + } + q6apm_lpass_dai_shutdown(substream, dai); +} + +static int q6i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct clk *sysclk; + bool *enabled; + int ret = 0; + + switch (clk_id) { + case LPAIF_MI2S_MCLK: + sysclk = dai_data->priv[dai->id].mclk; + enabled = &dai_data->priv[dai->id].mclk_enabled; + break; + case LPAIF_MI2S_BCLK: + sysclk = dai_data->priv[dai->id].bclk; + enabled = &dai_data->priv[dai->id].bclk_enabled; + break; + case LPAIF_MI2S_ECLK: + sysclk = dai_data->priv[dai->id].eclk; + enabled = &dai_data->priv[dai->id].eclk_enabled; + break; + default: + break; + } + + if (sysclk) { + clk_set_rate(sysclk, freq); + ret = clk_prepare_enable(sysclk); + if (ret) { + dev_err(dai->dev, "Error, Unable to prepare (%d) sysclk\n", clk_id); + return ret; + } + + *enabled = true; + } + + return ret; +} + static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); @@ -267,17 +329,16 @@ static const struct snd_soc_dai_ops q6dma_ops = { .shutdown = q6apm_lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, - .trigger = q6apm_lpass_dai_trigger, }; static const struct snd_soc_dai_ops q6i2s_ops = { .prepare = q6apm_lpass_dai_prepare, - .startup = q6apm_lpass_dai_startup, - .shutdown = q6apm_lpass_dai_shutdown, + .startup = q6i2s_dai_startup, + .shutdown = q6i2s_lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, .set_fmt = q6i2s_set_fmt, - .trigger = q6apm_lpass_dai_trigger, + .set_sysclk = q6i2s_set_sysclk, }; static const struct snd_soc_dai_ops q6hdmi_ops = { @@ -286,7 +347,6 @@ static const struct snd_soc_dai_ops q6hdmi_ops = { .shutdown = q6apm_lpass_dai_shutdown, .hw_params = q6hdmi_hw_params, .set_fmt = q6i2s_set_fmt, - .trigger = q6apm_lpass_dai_trigger, }; static const struct snd_soc_component_driver q6apm_lpass_dai_component = { @@ -294,9 +354,61 @@ static const struct snd_soc_component_driver q6apm_lpass_dai_component = { .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, .be_pcm_base = AUDIOREACH_BE_PCM_BASE, .use_dai_pcm_id = true, - .remove_order = SND_SOC_COMP_ORDER_FIRST, }; +static int of_q6apm_parse_dai_data(struct device *dev, + struct q6apm_lpass_dai_data *data) +{ + struct device_node *node; + int ret; + + for_each_child_of_node(dev->of_node, node) { + struct q6apm_dai_priv_data *priv; + int id; + + ret = of_property_read_u32(node, "reg", &id); + if (ret || id < 0 || id >= APM_PORT_MAX) { + dev_err(dev, "valid dai id not found:%d\n", ret); + continue; + } + + switch (id) { + /* MI2S specific properties */ + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + priv = &data->priv[id]; + priv->mclk = of_clk_get_by_name(node, "mclk"); + if (IS_ERR(priv->mclk)) { + if (PTR_ERR(priv->mclk) == -EPROBE_DEFER) + return dev_err_probe(dev, PTR_ERR(priv->mclk), + "unable to get mi2s mclk\n"); + priv->mclk = NULL; + } + + priv->bclk = of_clk_get_by_name(node, "bclk"); + if (IS_ERR(priv->bclk)) { + if (PTR_ERR(priv->bclk) == -EPROBE_DEFER) + return dev_err_probe(dev, PTR_ERR(priv->bclk), + "unable to get mi2s bclk\n"); + priv->bclk = NULL; + } + + priv->eclk = of_clk_get_by_name(node, "eclk"); + if (IS_ERR(priv->eclk)) { + if (PTR_ERR(priv->eclk) == -EPROBE_DEFER) + return dev_err_probe(dev, PTR_ERR(priv->eclk), + "unable to get mi2s eclk\n"); + priv->eclk = NULL; + } + break; + default: + break; + } + } + + return 0; +} + static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) { struct q6dsp_audio_port_dai_driver_config cfg; @@ -304,12 +416,16 @@ static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) struct snd_soc_dai_driver *dais; struct device *dev = &pdev->dev; int num_dais; + int ret; dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); if (!dai_data) return -ENOMEM; dev_set_drvdata(dev, dai_data); + ret = of_q6apm_parse_dai_data(dev, dai_data); + if (ret) + return ret; memset(&cfg, 0, sizeof(cfg)); cfg.q6i2s_ops = &q6i2s_ops; diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/q6prm.h index 8296370e3cbf7..a00d1eda1e708 100644 --- a/sound/soc/qcom/qdsp6/q6prm.h +++ b/sound/soc/qcom/qdsp6/q6prm.h @@ -3,6 +3,10 @@ #ifndef __Q6PRM_H__ #define __Q6PRM_H__ +#define LPAIF_MI2S_MCLK 1 +#define LPAIF_MI2S_BCLK 2 +#define LPAIF_MI2S_ECLK 3 + /* Clock ID for Primary I2S IBIT */ #define Q6PRM_LPASS_CLK_ID_PRI_MI2S_IBIT 0x100 /* Clock ID for Primary I2S EBIT */ From 1e0c131600e7a3499000293991308f0fb3d55a97 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 9 Mar 2026 16:43:00 +0530 Subject: [PATCH 1009/1058] ASoC: qcom: sc8280xp: ASoC: qcom: sc8280xp: enhance machine driver for board-specific config The sc8280xp machine driver is currently written with a largely SoC-centric view and assumes a uniform audio topology across all boards. In practice, multiple products based on the same SoC use different board designs and external audio components, which require board-specific configuration to function correctly. Several Qualcomm platforms like talos integrate third-party audio codecs or use different external audio paths. These designs often require additional configuration such as explicit MI2S MCLK settings for audio to work. This change enhances the sc8280xp machine driver to support board-specific configuration such as allowing each board variant to provide its own DAPM widgets and routes, reflecting the actual audio components and connectors present and enabling MI2S MCLK programming for boards that use external codecs requiring a stable master clock. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 201 ++++++++++++++++++++++++++++++++++---- 1 file changed, 181 insertions(+), 20 deletions(-) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index f8a5bdac892bd..a07c015ba04be 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -13,17 +13,62 @@ #include #include #include "qdsp6/q6afe.h" +#include "qdsp6/q6apm.h" +#include "qdsp6/q6prm.h" #include "common.h" #include "sdw.h" +#define MCLK_FREQ 12288000 +#define MCLK_NATIVE_FREQ 11289600 + +static struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("DP0 Jack", NULL), + SND_SOC_DAPM_SPK("DP1 Jack", NULL), + SND_SOC_DAPM_SPK("DP2 Jack", NULL), + SND_SOC_DAPM_SPK("DP3 Jack", NULL), + SND_SOC_DAPM_SPK("DP4 Jack", NULL), + SND_SOC_DAPM_SPK("DP5 Jack", NULL), + SND_SOC_DAPM_SPK("DP6 Jack", NULL), + SND_SOC_DAPM_SPK("DP7 Jack", NULL), +}; + +struct snd_soc_common { + char *driver_name; + const struct snd_soc_dapm_widget *dapm_widgets; + int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + int num_dapm_routes; + bool mi2s_mclk_enable; +}; + struct sc8280xp_snd_data { bool stream_prepared[AFE_PORT_MAX]; struct snd_soc_card *card; struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; + struct snd_soc_common *snd_soc_common_priv; bool jack_setup; }; +static inline int sc8280xp_get_mclk_feq(unsigned int rate) +{ + int freq = MCLK_FREQ; + + switch (rate) { + case SNDRV_PCM_RATE_11025: + case SNDRV_PCM_RATE_44100: + case SNDRV_PCM_RATE_88200: + freq = MCLK_NATIVE_FREQ; + break; + default: + break; + } + + return freq; +} + static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) { struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); @@ -33,10 +78,6 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) int dp_pcm_id = 0; switch (cpu_dai->id) { - case PRIMARY_MI2S_RX...QUATERNARY_MI2S_TX: - case QUINARY_MI2S_RX...QUINARY_MI2S_TX: - snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - break; case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: /* @@ -98,6 +139,42 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); + int mclk_freq = sc8280xp_get_mclk_feq(params_rate(params)); + + switch (cpu_dai->id) { + case PRIMARY_MI2S_RX...QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX...QUINARY_MI2S_TX: + snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (rtd->dai_link->num_codecs) { + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + + snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_CBC_CFC | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S); + + snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, + SND_SOC_CLOCK_IN); + } + + if (data->snd_soc_common_priv->mi2s_mclk_enable) + snd_soc_dai_set_sysclk(cpu_dai, + LPAIF_MI2S_MCLK, mclk_freq, + SND_SOC_CLOCK_IN); + break; + default: + break; + }; + + return 0; +} + static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -119,6 +196,7 @@ static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) static const struct snd_soc_ops sc8280xp_be_ops = { .startup = qcom_snd_sdw_startup, .shutdown = qcom_snd_sdw_shutdown, + .hw_params = sc8280xp_snd_hw_params, .hw_free = sc8280xp_snd_hw_free, .prepare = sc8280xp_snd_prepare, }; @@ -147,38 +225,121 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; - card->owner = THIS_MODULE; + /* Allocate the private data */ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; + data->snd_soc_common_priv = (struct snd_soc_common *)of_device_get_match_data(dev); + if (!data->snd_soc_common_priv) + return -ENOMEM; + + card->owner = THIS_MODULE; card->dev = dev; dev_set_drvdata(dev, card); snd_soc_card_set_drvdata(card, data); + card->dapm_widgets = data->snd_soc_common_priv->dapm_widgets; + card->num_dapm_widgets = data->snd_soc_common_priv->num_dapm_widgets; + card->dapm_routes = data->snd_soc_common_priv->dapm_routes; + card->num_dapm_routes = data->snd_soc_common_priv->num_dapm_routes; + ret = qcom_snd_parse_of(card); if (ret) return ret; - card->driver_name = of_device_get_match_data(dev); + card->driver_name = data->snd_soc_common_priv->driver_name; sc8280xp_add_be_ops(card); return devm_snd_soc_register_card(dev, card); } +static struct snd_soc_common kaanapali_priv_data = { + .driver_name = "kaanapali", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common qcs9100_priv_data = { + .driver_name = "sa8775p", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common qcs615_priv_data = { + .driver_name = "qcs615", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), + .mi2s_mclk_enable = true, +}; + +static struct snd_soc_common qcm6490_priv_data = { + .driver_name = "qcm6490", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common qcs6490_priv_data = { + .driver_name = "qcs6490", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common qcs8275_priv_data = { + .driver_name = "qcs8300", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common sc8280xp_priv_data = { + .driver_name = "sc8280xp", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common shikra_priv_data = { + .driver_name = "shikra", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common sm8450_priv_data = { + .driver_name = "sm8450", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common sm8550_priv_data = { + .driver_name = "sm8550", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common sm8650_priv_data = { + .driver_name = "sm8650", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static struct snd_soc_common sm8750_priv_data = { + .driver_name = "sm8750", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + static const struct of_device_id snd_sc8280xp_dt_match[] = { - {.compatible = "qcom,kaanapali-sndcard", "kaanapali"}, - {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, - {.compatible = "qcom,qcs615-sndcard", "qcs615"}, - {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, - {.compatible = "qcom,qcs8275-sndcard", "qcs8300"}, - {.compatible = "qcom,qcs9075-sndcard", "sa8775p"}, - {.compatible = "qcom,qcs9100-sndcard", "sa8775p"}, - {.compatible = "qcom,sc8280xp-sndcard", "sc8280xp"}, - {.compatible = "qcom,shikra-sndcard", "shikra"}, - {.compatible = "qcom,sm8450-sndcard", "sm8450"}, - {.compatible = "qcom,sm8550-sndcard", "sm8550"}, - {.compatible = "qcom,sm8650-sndcard", "sm8650"}, - {.compatible = "qcom,sm8750-sndcard", "sm8750"}, + { .compatible = "qcom,kaanapali-sndcard", .data = &kaanapali_priv_data }, + { .compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data }, + { .compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data }, + { .compatible = "qcom,qcs6490-rb3gen2-sndcard", .data = &qcs6490_priv_data }, + { .compatible = "qcom,qcs8275-sndcard", .data = &qcs8275_priv_data }, + { .compatible = "qcom,qcs9075-sndcard", .data = &qcs9100_priv_data }, + { .compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data }, + { .compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data }, + { .compatible = "qcom,shikra-sndcard", .data = &shikra_priv_data }, + { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, + { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, + { .compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data }, + { .compatible = "qcom,sm8750-sndcard", .data = &sm8750_priv_data }, {} }; @@ -194,4 +355,4 @@ static struct platform_driver snd_sc8280xp_driver = { module_platform_driver(snd_sc8280xp_driver); MODULE_AUTHOR("Srinivas Kandagatla Date: Fri, 29 May 2026 14:25:00 +0530 Subject: [PATCH 1010/1058] dt-bindings: sound: qcom,q6apm-lpass-dais: describe backend clocks Document the clock names that can appear in q6apm backend DAI child nodes. The LPASS backend clock description is no longer limited to MI2S. Audio IF TDM backends can use the same child-node clocks, so the binding needs to describe the valid names explicitly. Document "mclk", "bclk" and "eclk" and update the example accordingly. Signed-off-by: Prasad Kumpatla --- .../bindings/sound/qcom,q6apm-lpass-dais.yaml | 25 +++++++++++-------- sound/soc/qcom/sc8280xp.c | 13 +--------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml index 1d770cbcb058a..1a17930760804 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml @@ -27,23 +27,25 @@ properties: '#size-cells': const: 0 -# Digital Audio Interfaces patternProperties: '^dai@[0-9]+$': type: object description: - Q6DSP Digital Audio Interfaces. + Optional per-DAI clock description for LPASS backends. properties: reg: description: - Digital Audio Interface ID + Digital Audio Interface ID. clocks: minItems: 1 maxItems: 3 clock-names: + description: + Supported names are `mclk`, `bclk` and `eclk` depending on the + interface clock required by the backend. minItems: 1 maxItems: 3 @@ -53,22 +55,23 @@ required: - compatible - '#sound-dai-cells' +additionalProperties: false + unevaluatedProperties: false examples: - | - #include + #include - bedais { + dais { compatible = "qcom,q6apm-lpass-dais"; - #sound-dai-cells = <1>; #address-cells = <1>; #size-cells = <0>; + #sound-dai-cells = <1>; - dai@16 { - reg = ; - clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 - LPASS_CLK_ATTRIBUTE_COUPLE_NO>; - clock-names = "mclk"; + dai@0 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; }; }; diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index a07c015ba04be..023c2a522aa25 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -151,17 +151,6 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, case PRIMARY_MI2S_RX...QUATERNARY_MI2S_TX: case QUINARY_MI2S_RX...QUINARY_MI2S_TX: snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - if (rtd->dai_link->num_codecs) { - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - - snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_CBC_CFC | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_I2S); - - snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, - SND_SOC_CLOCK_IN); - } if (data->snd_soc_common_priv->mi2s_mclk_enable) snd_soc_dai_set_sysclk(cpu_dai, @@ -355,4 +344,4 @@ static struct platform_driver snd_sc8280xp_driver = { module_platform_driver(snd_sc8280xp_driver); MODULE_AUTHOR("Srinivas Kandagatla Date: Fri, 29 May 2026 14:25:00 +0530 Subject: [PATCH 1011/1058] dt-bindings: sound: qcom,q6dsp-lpass-ports: add Audio IF clocks Add LPASS Audio IF IBIT and EBIT clock IDs used by newer backend interfaces. Signed-off-by: Prasad Kumpatla --- .../sound/qcom,q6dsp-lpass-ports.h | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h index 45850f2d43425..bc860fcbf0f51 100644 --- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h +++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h @@ -233,6 +233,63 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 70 +/** Clock ID of the Audio Intf 0 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF0_IBIT 71 +/** Clock ID of the Audio Intf 0 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF0_EBIT 72 +/** Clock ID of the Audio Intf 1 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF1_IBIT 73 +/** Clock ID of the Audio Intf 1 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF1_EBIT 74 +/** Clock ID of the Audio Intf 2 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF2_IBIT 75 +/** Clock ID of the Audio Intf 2 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF2_EBIT 76 +/** Clock ID of the Audio Intf 3 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF3_IBIT 77 +/** Clock ID of the Audio Intf 3 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF3_EBIT 78 +/** Clock ID of the Audio Intf 4 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF4_IBIT 79 +/** Clock ID of the Audio Intf 4 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF4_EBIT 80 +/** Clock ID of the Audio Intf 5 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF5_IBIT 81 +/** Clock ID of the Audio Intf 5 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF5_EBIT 82 +/** Clock ID of the Audio Intf 6 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF6_IBIT 83 +/** Clock ID of the Audio Intf 6 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF6_EBIT 84 +/** Clock ID of the Audio Intf 7 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF7_IBIT 85 +/** Clock ID of the Audio Intf 7 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF7_EBIT 86 +/** Clock ID of the Audio Intf 8 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF8_IBIT 87 +/** Clock ID of the Audio Intf 8 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF8_EBIT 88 +/** Clock ID of the Audio Intf 9 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF9_IBIT 89 +/** Clock ID of the Audio Intf 9 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF9_EBIT 90 +/** Clock ID of the Audio Intf 10 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF10_IBIT 91 +/** Clock ID of the Audio Intf 10 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF10_EBIT 92 +/** Clock ID of the Audio Intf 11 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF11_IBIT 93 +/** Clock ID of the Audio Intf 11 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF11_EBIT 94 +/** Clock ID of the Audio Intf 12 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF12_IBIT 95 +/** Clock ID of the Audio Intf 12 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF12_EBIT 96 +/** Clock ID of the Audio VA Intf 0 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_VA_INTF0_IBIT 97 +/** Clock ID of the Audio VA Intf 0 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_VA_INTF0_EBIT 98 + #define LPASS_HW_AVTIMER_VOTE 101 #define LPASS_HW_MACRO_VOTE 102 #define LPASS_HW_DCODEC_VOTE 103 From 0204a6f026ec4d7645d76ec2adfbd72265478e31 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Fri, 29 May 2026 14:25:00 +0530 Subject: [PATCH 1012/1058] ASoC: qcom: q6prm: add Audio IF clock IDs Add the LPASS Audio IF clock IDs used by newer backend interfaces. Audio IF TDM backends request the interface bit clock through q6prm. Add the missing Audio IF IBIT and EBIT IDs to the clock tables so those clocks can be requested from the APM clock controller. Also add generic selector values for backend .set_sysclk() users so the same API can request mclk, bclk or eclk. Signed-off-by: Prasad Kumpatla --- sound/soc/qcom/qdsp6/q6prm-clocks.c | 28 +++++++++++ sound/soc/qcom/qdsp6/q6prm.h | 77 ++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6prm-clocks.c b/sound/soc/qcom/qdsp6/q6prm-clocks.c index 51b131fa95316..b6755da6a6da8 100644 --- a/sound/soc/qcom/qdsp6/q6prm-clocks.c +++ b/sound/soc/qcom/qdsp6/q6prm-clocks.c @@ -64,6 +64,34 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK), Q6PRM_CLK(LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_EBIT), Q6DSP_VOTE_CLK(LPASS_HW_MACRO_VOTE, Q6PRM_HW_CORE_ID_LPASS, "LPASS_HW_MACRO"), Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6PRM_HW_CORE_ID_DCODEC, diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/q6prm.h index a00d1eda1e708..a4903990f859a 100644 --- a/sound/soc/qcom/qdsp6/q6prm.h +++ b/sound/soc/qcom/qdsp6/q6prm.h @@ -3,9 +3,13 @@ #ifndef __Q6PRM_H__ #define __Q6PRM_H__ -#define LPAIF_MI2S_MCLK 1 -#define LPAIF_MI2S_BCLK 2 -#define LPAIF_MI2S_ECLK 3 +#define LPAIF_MI2S_TDM_MCLK 1 +#define LPAIF_MI2S_TDM_BCLK 2 +#define LPAIF_MI2S_TDM_ECLK 3 + +#define LPAIF_MI2S_MCLK LPAIF_MI2S_TDM_MCLK +#define LPAIF_MI2S_BCLK LPAIF_MI2S_TDM_BCLK +#define LPAIF_MI2S_ECLK LPAIF_MI2S_TDM_ECLK /* Clock ID for Primary I2S IBIT */ #define Q6PRM_LPASS_CLK_ID_PRI_MI2S_IBIT 0x100 @@ -57,15 +61,15 @@ #define Q6PRM_LPASS_CLK_ID_QUI_MI2S_OSR 0x116 /* Clock ID for MCLK1 */ -#define Q6PRM_LPASS_CLK_ID_MCLK_1 0x300 +#define Q6PRM_LPASS_CLK_ID_MCLK_1 0x300 /* Clock ID for MCLK2 */ -#define Q6PRM_LPASS_CLK_ID_MCLK_2 0x301 +#define Q6PRM_LPASS_CLK_ID_MCLK_2 0x301 /* Clock ID for MCLK3 */ -#define Q6PRM_LPASS_CLK_ID_MCLK_3 0x302 +#define Q6PRM_LPASS_CLK_ID_MCLK_3 0x302 /* Clock ID for MCLK4 */ -#define Q6PRM_LPASS_CLK_ID_MCLK_4 0x303 +#define Q6PRM_LPASS_CLK_ID_MCLK_4 0x303 /* Clock ID for MCLK5 */ -#define Q6PRM_LPASS_CLK_ID_MCLK_5 0x304 +#define Q6PRM_LPASS_CLK_ID_MCLK_5 0x304 #define Q6PRM_LPASS_CLK_ID_WSA_CORE_MCLK 0x305 #define Q6PRM_LPASS_CLK_ID_WSA_CORE_NPL_MCLK 0x306 @@ -98,6 +102,63 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define Q6PRM_LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 0x318 +/** Clock ID of the Audio Intf 0 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_IBIT 0x500 +/** Clock ID of the Audio Intf 0 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_EBIT 0x501 +/** Clock ID of the Audio Intf 1 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_IBIT 0x502 +/** Clock ID of the Audio Intf 1 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_EBIT 0x503 +/** Clock ID of the Audio Intf 2 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_IBIT 0x504 +/** Clock ID of the Audio Intf 2 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_EBIT 0x505 +/** Clock ID of the Audio Intf 3 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_IBIT 0x506 +/** Clock ID of the Audio Intf 3 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_EBIT 0x507 +/** Clock ID of the Audio Intf 4 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_IBIT 0x508 +/** Clock ID of the Audio Intf 4 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_EBIT 0x509 +/** Clock ID of the Audio Intf 5 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_IBIT 0x50A +/** Clock ID of the Audio Intf 5 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_EBIT 0x50B +/** Clock ID of the Audio Intf 6 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_IBIT 0x50C +/** Clock ID of the Audio Intf 6 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_EBIT 0x50D +/** Clock ID of the Audio Intf 7 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_IBIT 0x50E +/** Clock ID of the Audio Intf 7 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_EBIT 0x50F +/** Clock ID of the Audio Intf 8 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_IBIT 0x510 +/** Clock ID of the Audio Intf 8 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_EBIT 0x511 +/** Clock ID of the Audio Intf 9 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_IBIT 0x512 +/** Clock ID of the Audio Intf 9 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_EBIT 0x513 +/** Clock ID of the Audio Intf 10 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_IBIT 0x514 +/** Clock ID of the Audio Intf 10 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_EBIT 0x515 +/** Clock ID of the Audio Intf 11 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_IBIT 0x516 +/** Clock ID of the Audio Intf 11 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_EBIT 0x517 +/** Clock ID of the Audio Intf 12 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_IBIT 0x518 +/** Clock ID of the Audio Intf 12 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_EBIT 0x519 +/** Clock ID of the Audio VA Intf 0 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_IBIT 0x550 +/** Clock ID of the Audio VA Intf 0 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_EBIT 0x551 + #define Q6PRM_LPASS_CLK_SRC_INTERNAL 1 #define Q6PRM_LPASS_CLK_ROOT_DEFAULT 0 #define Q6PRM_HW_CORE_ID_LPASS 1 From 8b6db3b4bc77d2d553f94e35b6017dfbee66ed8d Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Fri, 29 May 2026 14:25:01 +0530 Subject: [PATCH 1013/1058] ASoC: qcom: q6apm-lpass-dais: extend child clocks to TDM Reuse the LPASS backend child-clock support for both MI2S and TDM. Switch the child clock lookup to a common helper so each backend can pick up optional "mclk", "bclk" or "eclk" entries from its DT child node. Route .set_sysclk() through the shared helper and use the same shutdown path so enabled backend clocks are disabled consistently. Keep TDM slot programming in q6apm-lpass-dais so machine drivers can configure the backend port and still reuse the common child-clock support. Signed-off-by: Prasad Kumpatla --- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 322 +++++++++++++++--------- 1 file changed, 206 insertions(+), 116 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 1e739a474936c..ff92ac7e522d3 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -25,7 +25,9 @@ struct q6apm_dai_priv_data { struct clk *mclk; struct clk *bclk; struct clk *eclk; - bool mclk_enabled, bclk_enabled, eclk_enabled; + bool mclk_enabled; + bool bclk_enabled; + bool eclk_enabled; }; struct q6apm_lpass_dai_data { @@ -35,6 +37,54 @@ struct q6apm_lpass_dai_data { struct q6apm_dai_priv_data priv[APM_PORT_MAX]; }; +static struct clk *q6apm_lpass_get_child_clk(struct device *dev, struct device_node *node, + const char *name) +{ + struct clk *clk; + + clk = devm_get_clk_from_child(dev, node, name); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) == -EPROBE_DEFER) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(clk), + "unable to get %s\n", name)); + + return NULL; + } + + return clk; +} + +static int of_q6apm_parse_dai_data(struct device *dev, + struct q6apm_lpass_dai_data *data) +{ + struct device_node *node; + + for_each_child_of_node(dev->of_node, node) { + struct q6apm_dai_priv_data *priv; + int ret; + int id; + + ret = of_property_read_u32(node, "reg", &id); + if (ret || id < 0 || id >= APM_PORT_MAX) + continue; + + priv = &data->priv[id]; + priv->mclk = q6apm_lpass_get_child_clk(dev, node, "mclk"); + if (IS_ERR(priv->mclk)) + return PTR_ERR(priv->mclk); + + priv->bclk = q6apm_lpass_get_child_clk(dev, node, "bclk"); + if (IS_ERR(priv->bclk)) + return PTR_ERR(priv->bclk); + + priv->eclk = q6apm_lpass_get_child_clk(dev, node, "eclk"); + if (IS_ERR(priv->eclk)) + return PTR_ERR(priv->eclk); + } + + return 0; +} + static int q6dma_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, const unsigned int *tx_ch_mask, @@ -161,7 +211,7 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct rc = q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; if (rc < 0) - dev_err(dai->dev, "fail to close APM port (%d)\n", rc); + dev_err(dai->dev, "failed to stop APM port (%d)\n", rc); } if (dai_data->graph[dai->id]) { @@ -170,6 +220,58 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct } } +static void q6lpass_disable_clocks(struct q6apm_dai_priv_data *priv) +{ + if (priv->mclk_enabled) { + clk_disable_unprepare(priv->mclk); + priv->mclk_enabled = false; + } + + if (priv->bclk_enabled) { + clk_disable_unprepare(priv->bclk); + priv->bclk_enabled = false; + } + + if (priv->eclk_enabled) { + clk_disable_unprepare(priv->eclk); + priv->eclk_enabled = false; + } +} + +static void q6lpass_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + + q6lpass_disable_clocks(&dai_data->priv[dai->id]); + q6apm_lpass_dai_shutdown(substream, dai); +} + +static int q6apm_lpass_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!dai_data->is_port_started[dai->id]) { + ret = q6apm_graph_start(dai_data->graph[dai->id]); + if (ret < 0) + dev_err(dai->dev, "Failed to start APM port %d\n", dai->id); + else + dai_data->is_port_started[dai->id] = true; + } + break; + default: + break; + } + + return ret; +} + static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); @@ -182,18 +284,14 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - q6apm_graph_close(dai_data->graph[dai->id]); - dai_data->graph[dai->id] = NULL; - } } /** * It is recommend to load DSP with source graph first and then sink * graph, so sequence for playback and capture will be different */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !dai_data->graph[dai->id]) { + graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream); if (IS_ERR(graph)) { dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id); rc = PTR_ERR(graph); @@ -214,14 +312,6 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s dev_err(dai->dev, "Failed to prepare Graph %d\n", rc); goto err; } - - rc = q6apm_graph_start(dai_data->graph[dai->id]); - if (rc < 0) { - dev_err(dai->dev, "Failed to start APM port %d\n", dai->id); - goto err; - } - dai_data->is_port_started[dai->id] = true; - return 0; err: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -238,7 +328,7 @@ static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct s int graph_id = dai->id; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id); + graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream); if (IS_ERR(graph)) { dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id); return PTR_ERR(graph); @@ -249,96 +339,134 @@ static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct s return 0; } -static int q6i2s_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - return q6apm_lpass_dai_startup(substream, dai); + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; + + cfg->fmt = fmt; + + return 0; } -static void q6i2s_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, int slot_width) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; + unsigned int cap_mask; - if (dai_data->priv[dai->id].mclk_enabled) { - clk_disable_unprepare(dai_data->priv[dai->id].mclk); - dai_data->priv[dai->id].mclk_enabled = false; + if (slot_width != 16 && slot_width != 32) { + dev_err(dai->dev, "%s: invalid slot_width %d\n", + __func__, slot_width); + return -EINVAL; } - if (dai_data->priv[dai->id].bclk_enabled) { - clk_disable_unprepare(dai_data->priv[dai->id].bclk); - dai_data->priv[dai->id].bclk_enabled = false; + switch (slots) { + case 2: + cap_mask = 0x03; + break; + case 4: + cap_mask = 0x0f; + break; + case 8: + cap_mask = 0xff; + break; + case 16: + cap_mask = 0xffff; + break; + default: + dev_err(dai->dev, "%s: invalid slots %d\n", + __func__, slots); + return -EINVAL; } - if (dai_data->priv[dai->id].eclk_enabled) { - clk_disable_unprepare(dai_data->priv[dai->id].eclk); - dai_data->priv[dai->id].eclk_enabled = false; + switch (dai->id) { + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + cfg->nslots_per_frame = slots; + cfg->slot_width = slot_width; + cfg->slot_mask = ((dai->id & 0x1) ? tx_mask : rx_mask) & cap_mask; + break; + default: + dev_err(dai->dev, "%s: invalid dai id 0x%x\n", + __func__, dai->id); + return -EINVAL; } - q6apm_lpass_dai_shutdown(substream, dai); + + return 0; } -static int q6i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) +static int q6i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); - struct clk *sysclk; - bool *enabled; - int ret = 0; + struct q6apm_dai_priv_data *priv = &dai_data->priv[dai->id]; + struct clk *sysclk = NULL; + bool *enabled = NULL; + int ret; switch (clk_id) { - case LPAIF_MI2S_MCLK: - sysclk = dai_data->priv[dai->id].mclk; - enabled = &dai_data->priv[dai->id].mclk_enabled; + case LPAIF_MI2S_TDM_MCLK: + sysclk = priv->mclk; + enabled = &priv->mclk_enabled; break; - case LPAIF_MI2S_BCLK: - sysclk = dai_data->priv[dai->id].bclk; - enabled = &dai_data->priv[dai->id].bclk_enabled; + case LPAIF_MI2S_TDM_BCLK: + sysclk = priv->bclk; + enabled = &priv->bclk_enabled; break; - case LPAIF_MI2S_ECLK: - sysclk = dai_data->priv[dai->id].eclk; - enabled = &dai_data->priv[dai->id].eclk_enabled; + case LPAIF_MI2S_TDM_ECLK: + sysclk = priv->eclk; + enabled = &priv->eclk_enabled; break; default: - break; + return 0; } - if (sysclk) { - clk_set_rate(sysclk, freq); - ret = clk_prepare_enable(sysclk); - if (ret) { - dev_err(dai->dev, "Error, Unable to prepare (%d) sysclk\n", clk_id); - return ret; - } + if (!sysclk || !freq) + return 0; - *enabled = true; - } + ret = clk_set_rate(sysclk, freq); + if (ret) + return ret; - return ret; -} + if (*enabled) + return 0; -static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); - struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; + ret = clk_prepare_enable(sysclk); + if (ret) + return ret; - cfg->fmt = fmt; + *enabled = true; return 0; } +static int q6lpass_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + return q6i2s_set_sysclk(dai, clk_id, freq, dir); +} + static const struct snd_soc_dai_ops q6dma_ops = { .prepare = q6apm_lpass_dai_prepare, .startup = q6apm_lpass_dai_startup, .shutdown = q6apm_lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, + .trigger = q6apm_lpass_dai_trigger, }; static const struct snd_soc_dai_ops q6i2s_ops = { .prepare = q6apm_lpass_dai_prepare, - .startup = q6i2s_dai_startup, - .shutdown = q6i2s_lpass_dai_shutdown, + .startup = q6apm_lpass_dai_startup, + .shutdown = q6lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, .set_fmt = q6i2s_set_fmt, - .set_sysclk = q6i2s_set_sysclk, + .set_sysclk = q6lpass_set_sysclk, + .trigger = q6apm_lpass_dai_trigger, }; static const struct snd_soc_dai_ops q6hdmi_ops = { @@ -347,6 +475,19 @@ static const struct snd_soc_dai_ops q6hdmi_ops = { .shutdown = q6apm_lpass_dai_shutdown, .hw_params = q6hdmi_hw_params, .set_fmt = q6i2s_set_fmt, + .trigger = q6apm_lpass_dai_trigger, +}; + +static const struct snd_soc_dai_ops q6tdm_ops = { + .prepare = q6apm_lpass_dai_prepare, + .startup = q6apm_lpass_dai_startup, + .shutdown = q6lpass_dai_shutdown, + .set_channel_map = q6dma_set_channel_map, + .set_tdm_slot = q6tdm_set_tdm_slot, + .hw_params = q6dma_hw_params, + .set_fmt = q6i2s_set_fmt, + .set_sysclk = q6lpass_set_sysclk, + .trigger = q6apm_lpass_dai_trigger, }; static const struct snd_soc_component_driver q6apm_lpass_dai_component = { @@ -354,61 +495,9 @@ static const struct snd_soc_component_driver q6apm_lpass_dai_component = { .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, .be_pcm_base = AUDIOREACH_BE_PCM_BASE, .use_dai_pcm_id = true, + .remove_order = SND_SOC_COMP_ORDER_FIRST, }; -static int of_q6apm_parse_dai_data(struct device *dev, - struct q6apm_lpass_dai_data *data) -{ - struct device_node *node; - int ret; - - for_each_child_of_node(dev->of_node, node) { - struct q6apm_dai_priv_data *priv; - int id; - - ret = of_property_read_u32(node, "reg", &id); - if (ret || id < 0 || id >= APM_PORT_MAX) { - dev_err(dev, "valid dai id not found:%d\n", ret); - continue; - } - - switch (id) { - /* MI2S specific properties */ - case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: - case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: - priv = &data->priv[id]; - priv->mclk = of_clk_get_by_name(node, "mclk"); - if (IS_ERR(priv->mclk)) { - if (PTR_ERR(priv->mclk) == -EPROBE_DEFER) - return dev_err_probe(dev, PTR_ERR(priv->mclk), - "unable to get mi2s mclk\n"); - priv->mclk = NULL; - } - - priv->bclk = of_clk_get_by_name(node, "bclk"); - if (IS_ERR(priv->bclk)) { - if (PTR_ERR(priv->bclk) == -EPROBE_DEFER) - return dev_err_probe(dev, PTR_ERR(priv->bclk), - "unable to get mi2s bclk\n"); - priv->bclk = NULL; - } - - priv->eclk = of_clk_get_by_name(node, "eclk"); - if (IS_ERR(priv->eclk)) { - if (PTR_ERR(priv->eclk) == -EPROBE_DEFER) - return dev_err_probe(dev, PTR_ERR(priv->eclk), - "unable to get mi2s eclk\n"); - priv->eclk = NULL; - } - break; - default: - break; - } - } - - return 0; -} - static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) { struct q6dsp_audio_port_dai_driver_config cfg; @@ -431,6 +520,7 @@ static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) cfg.q6i2s_ops = &q6i2s_ops; cfg.q6dma_ops = &q6dma_ops; cfg.q6hdmi_ops = &q6hdmi_ops; + cfg.q6tdm_ops = &q6tdm_ops; dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais); return devm_snd_soc_register_component(dev, &q6apm_lpass_dai_component, dais, num_dais); From da9a240727d384510bfde0171bbaf8b623b265cb Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Fri, 29 May 2026 21:24:37 +0530 Subject: [PATCH 1014/1058] ASoC: qcom: common: add DAI-node TDM slot helpers Add common helpers to parse standard dai-tdm-slot-* properties from the CPU and codec child nodes of a backend DAI link and apply the result to the active DAIs. QCOM machine drivers already use qcom_snd_parse_of() to build links from DT, but they lacked a shared helper to translate endpoint TDM properties into snd_soc_dai_set_tdm_slot() calls. Boards therefore had to carry ad hoc parsing or rely on non-standard DT properties. The new helpers parse the endpoint masks, validate the shared slot count and slot width, and program the CPU and codec DAIs with the resulting slot configuration. This keeps the DT description declarative and lets machine drivers reuse standard ASoC APIs for TDM backend setup. Signed-off-by: Prasad Kumpatla --- sound/soc/qcom/common.c | 154 ++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/common.h | 11 +++ 2 files changed, 165 insertions(+) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 2429c086673c8..767606ea3ab7b 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -24,6 +24,160 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { SND_SOC_DAPM_SPK("DP7 Jack", NULL), }; +static struct device_node *qcom_snd_get_link_node(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_card *card = rtd->card; + struct device_node *np; + struct device_node *cpu_np; + struct of_phandle_args args; + int ret; + + if (!card->dev || !card->dev->of_node) + return NULL; + + for_each_available_child_of_node(card->dev->of_node, np) { + cpu_np = of_get_child_by_name(np, "cpu"); + if (!cpu_np) + continue; + + ret = of_parse_phandle_with_args(cpu_np, "sound-dai", "#sound-dai-cells", 0, &args); + of_node_put(cpu_np); + if (ret) + continue; + + if (args.np == rtd->dai_link->cpus[0].of_node && + args.args_count == 1 && args.args[0] == cpu_dai->id) { + of_node_put(args.np); + return np; + } + + of_node_put(args.np); + } + + return NULL; +} + +static int qcom_snd_parse_tdm_slot(struct device_node *np, + struct qcom_snd_tdm_slot_cfg *cfg) +{ + memset(cfg, 0, sizeof(*cfg)); + + return snd_soc_of_parse_tdm_slot(np, &cfg->tx_mask, &cfg->rx_mask, + &cfg->slots, &cfg->slot_width); +} + +static int qcom_snd_normalize_tdm_slots(struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + unsigned int slots; + unsigned int slot_width; + + if (cpu_cfg->slots && codec_cfg->slots && cpu_cfg->slots != codec_cfg->slots) + return -EINVAL; + + if (cpu_cfg->slot_width && codec_cfg->slot_width && + cpu_cfg->slot_width != codec_cfg->slot_width) + return -EINVAL; + + slots = cpu_cfg->slots ?: codec_cfg->slots; + if (!slots) + return 0; + + slot_width = cpu_cfg->slot_width ?: codec_cfg->slot_width; + if (!slot_width) + return -EINVAL; + + cpu_cfg->slots = slots; + codec_cfg->slots = slots; + cpu_cfg->slot_width = slot_width; + codec_cfg->slot_width = slot_width; + + return 0; +} + +static int qcom_snd_parse_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + struct device_node *link_np; + struct device_node *cpu_np = NULL; + struct device_node *codec_np = NULL; + int ret; + + link_np = qcom_snd_get_link_node(rtd); + if (!link_np) + return -EINVAL; + + cpu_np = of_get_child_by_name(link_np, "cpu"); + codec_np = of_get_child_by_name(link_np, "codec"); + if (!cpu_np || !codec_np) { + ret = -EINVAL; + goto out; + } + + ret = qcom_snd_parse_tdm_slot(cpu_np, cpu_cfg); + if (ret) + goto out; + + ret = qcom_snd_parse_tdm_slot(codec_np, codec_cfg); +out: + of_node_put(codec_np); + of_node_put(cpu_np); + of_node_put(link_np); + + return ret; +} + +int qcom_snd_get_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + int ret; + + ret = qcom_snd_parse_dai_tdm_slots(rtd, cpu_cfg, codec_cfg); + if (ret) + return ret; + + return qcom_snd_normalize_tdm_slots(cpu_cfg, codec_cfg); +} +EXPORT_SYMBOL_GPL(qcom_snd_get_dai_tdm_slots); + +int qcom_snd_apply_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + struct qcom_snd_tdm_slot_cfg cpu_cfg; + struct qcom_snd_tdm_slot_cfg codec_cfg; + int i; + int ret; + + ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg); + if (ret) + return ret == -EINVAL ? 0 : ret; + + if (!cpu_cfg.slots) + return ret; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, cpu_cfg.tx_mask, cpu_cfg.rx_mask, + cpu_cfg.slots, cpu_cfg.slot_width); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + codec_cfg.tx_mask, + codec_cfg.rx_mask, + codec_cfg.slots, + codec_cfg.slot_width); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_snd_apply_dai_tdm_slots); + int qcom_snd_parse_of(struct snd_soc_card *card) { struct device *dev = card->dev; diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h index ee6662885593c..b73c25045e672 100644 --- a/sound/soc/qcom/common.h +++ b/sound/soc/qcom/common.h @@ -9,7 +9,18 @@ #define LPASS_MAX_PORT (SENARY_MI2S_TX + 1) +struct qcom_snd_tdm_slot_cfg { + unsigned int tx_mask; + unsigned int rx_mask; + unsigned int slots; + unsigned int slot_width; +}; + int qcom_snd_parse_of(struct snd_soc_card *card); +int qcom_snd_get_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg); +int qcom_snd_apply_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd); int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *jack, bool *jack_setup); int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, From 3e165a9e288ffbd2a263fd5fee4470746349d71c Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 3 Jun 2026 13:48:29 +0530 Subject: [PATCH 1015/1058] ASoC: qcom: sc8280xp: add Audio IF backend support Add Audio IF TDM backend handling to the sc8280xp machine driver. Use the common QCOM DAI-node TDM helper to parse standard dai-tdm-slot-* properties from the backend CPU and codec endpoints and apply them during TDM hw_params(). Derive the LPASS backend bit clock from runtime TDM parameters and request it through the backend child-clock path. Program the codec sysclk in the active stream path so the WSA885X playback sequence matches the working hardware flow. Signed-off-by: Prasad Kumpatla Signed-off-by: Pratyush Meduri --- sound/soc/qcom/sc8280xp.c | 185 +++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 53 deletions(-) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 023c2a522aa25..ccb105aa873dc 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include "qdsp6/q6afe.h" -#include "qdsp6/q6apm.h" #include "qdsp6/q6prm.h" #include "common.h" #include "sdw.h" @@ -21,7 +21,7 @@ #define MCLK_FREQ 12288000 #define MCLK_NATIVE_FREQ 11289600 -static struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { +static const struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_SPK("DP0 Jack", NULL), @@ -35,7 +35,7 @@ static struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { }; struct snd_soc_common { - char *driver_name; + const char *driver_name; const struct snd_soc_dapm_widget *dapm_widgets; int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; @@ -48,25 +48,69 @@ struct sc8280xp_snd_data { struct snd_soc_card *card; struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; - struct snd_soc_common *snd_soc_common_priv; + const struct snd_soc_common *snd_soc_common_priv; bool jack_setup; }; -static inline int sc8280xp_get_mclk_feq(unsigned int rate) +static int sc8280xp_tdm_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *cpu_dai) { - int freq = MCLK_FREQ; + int ret; - switch (rate) { - case SNDRV_PCM_RATE_11025: - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_88200: - freq = MCLK_NATIVE_FREQ; - break; - default: - break; + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (ret && ret != -EOPNOTSUPP) + dev_err(rtd->dev, "%s: failed to set cpu fmt: %d\n", __func__, ret); + + return ret < 0 && ret != -EOPNOTSUPP ? ret : 0; +} + +static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + struct qcom_snd_tdm_slot_cfg cpu_cfg; + struct qcom_snd_tdm_slot_cfg codec_cfg; + unsigned int bclk_freq; + int ret; + int i; + + ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg); + if (ret) + return ret == -EINVAL ? 0 : ret; + + if (!cpu_cfg.slots) + return 0; + + ret = sc8280xp_tdm_set_dai_fmt(rtd, cpu_dai); + if (ret) + return ret; + + ret = qcom_snd_apply_dai_tdm_slots(rtd); + if (ret) + return ret; + + bclk_freq = snd_soc_tdm_params_to_bclk(params, cpu_cfg.slot_width, cpu_cfg.slots, 1); + if (!bclk_freq) + return -EINVAL; + + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_TDM_BCLK, bclk_freq, SND_SOC_CLOCK_IN); + if (ret < 0 && ret != -EOPNOTSUPP) { + dev_err(rtd->dev, "%s: failed to set cpu sysclk: %d\n", __func__, ret); + return ret; } - return freq; + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, bclk_freq, SND_SOC_CLOCK_IN); + if (ret < 0 && ret != -EOPNOTSUPP) { + dev_err(rtd->dev, "%s: failed to set codec sysclk on %s: %d\n", + __func__, codec_dai->name, ret); + return ret; + } + } + + return 0; } static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) @@ -78,6 +122,8 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) int dp_pcm_id = 0; switch (cpu_dai->id) { + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + return sc8280xp_tdm_set_dai_fmt(rtd, cpu_dai); case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: /* @@ -109,6 +155,23 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } +static inline int sc8280xp_get_mclk_feq(unsigned int rate) +{ + int freq = MCLK_FREQ; + + switch (rate) { + case SNDRV_PCM_RATE_11025: + case SNDRV_PCM_RATE_44100: + case SNDRV_PCM_RATE_88200: + freq = MCLK_NATIVE_FREQ; + break; + default: + break; + } + + return freq; +} + static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -139,40 +202,57 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); + + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); +} + static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - int mclk_freq = sc8280xp_get_mclk_feq(params_rate(params)); + unsigned int mclk_freq = sc8280xp_get_mclk_feq(params_rate(params)); + int ret; switch (cpu_dai->id) { - case PRIMARY_MI2S_RX...QUATERNARY_MI2S_TX: - case QUINARY_MI2S_RX...QUINARY_MI2S_TX: - snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - - if (data->snd_soc_common_priv->mi2s_mclk_enable) - snd_soc_dai_set_sysclk(cpu_dai, - LPAIF_MI2S_MCLK, mclk_freq, + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (rtd->dai_link->num_codecs) { + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + + snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_CBC_CFC | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S); + + snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN); - break; + } + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + + if (!data->snd_soc_common_priv->mi2s_mclk_enable) + return 0; + + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_MCLK, + mclk_freq, SND_SOC_CLOCK_IN); + return ret < 0 && ret != -EOPNOTSUPP ? ret : 0; + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + return sc8280xp_tdm_hw_params(substream, params); default: break; - }; + } return 0; } -static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - - return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); -} - static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -215,14 +295,13 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - /* Allocate the private data */ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - data->snd_soc_common_priv = (struct snd_soc_common *)of_device_get_match_data(dev); + data->snd_soc_common_priv = of_device_get_match_data(dev); if (!data->snd_soc_common_priv) - return -ENOMEM; + return -EINVAL; card->owner = THIS_MODULE; card->dev = dev; @@ -242,44 +321,44 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) return devm_snd_soc_register_card(dev, card); } -static struct snd_soc_common kaanapali_priv_data = { +static const struct snd_soc_common kaanapali_priv_data = { .driver_name = "kaanapali", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common qcs9100_priv_data = { - .driver_name = "sa8775p", +static const struct snd_soc_common qcm6490_priv_data = { + .driver_name = "qcm6490", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common qcs615_priv_data = { +static const struct snd_soc_common qcs615_priv_data = { .driver_name = "qcs615", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), .mi2s_mclk_enable = true, }; -static struct snd_soc_common qcm6490_priv_data = { - .driver_name = "qcm6490", +static const struct snd_soc_common qcs6490_priv_data = { + .driver_name = "qcs6490", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common qcs6490_priv_data = { - .driver_name = "qcs6490", +static const struct snd_soc_common qcs8275_priv_data = { + .driver_name = "qcs8300", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common qcs8275_priv_data = { - .driver_name = "qcs8300", +static const struct snd_soc_common qcs9100_priv_data = { + .driver_name = "sa8775p", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common sc8280xp_priv_data = { +static const struct snd_soc_common sc8280xp_priv_data = { .driver_name = "sc8280xp", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), @@ -291,25 +370,25 @@ static const struct snd_soc_common shikra_priv_data = { .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common sm8450_priv_data = { +static const struct snd_soc_common sm8450_priv_data = { .driver_name = "sm8450", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common sm8550_priv_data = { +static const struct snd_soc_common sm8550_priv_data = { .driver_name = "sm8550", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common sm8650_priv_data = { +static const struct snd_soc_common sm8650_priv_data = { .driver_name = "sm8650", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), }; -static struct snd_soc_common sm8750_priv_data = { +static const struct snd_soc_common sm8750_priv_data = { .driver_name = "sm8750", .dapm_widgets = sc8280xp_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), @@ -344,4 +423,4 @@ static struct platform_driver snd_sc8280xp_driver = { module_platform_driver(snd_sc8280xp_driver); MODULE_AUTHOR("Srinivas Kandagatla Date: Mon, 1 Jun 2026 22:57:53 +0530 Subject: [PATCH 1016/1058] ASoC: qcom: qdsp6: add topology-driven Audio IF support Add topology parsing and media-format programming for Audio IF source and sink modules. Add the Audio IF module IDs, the required topology tokens, and a dedicated topology loader that stores the parsed interface configuration in the AudioReach module state. Also add the Audio IF media-format path that sends the interface configuration, hardware endpoint media format, and frame-duration parameters for Audio IF modules. This keeps the serial-interface configuration topology-driven while still allowing the machine driver to provide runtime slot and media format settings. The same Audio IF path can then be reused for TDM, PCM, and I2S style backends. PARAM_ID_HW_EP_FRAME_DURATION is programmed with a 1 ms frame duration (AUDIO_IF_FRAME_DURATION_US = 1000 us) because 1 ms is the standard interrupt period of the LPASS hardware endpoint for TDM, PCM, and I2S backends; it is the correct default for all supported serial-interface topologies. Normalization is enabled with the window [min=1 us, max=100000 us] as a safety net: the AudioReach DSP scheduler accepts any frame duration in that range, so a topology that specifies a non-1 ms period will not be rejected by the scheduler. The new UAPI tokens (AR_TKN_U32_MODULE_SYNC_SRC=262 through AR_TKN_U32_MODULE_INV_EXT_BIT_CLK=276) are not yet present in any shipped firmware topology blob; firmware must be updated to use these token values. Signed-off-by: Prasad Kumpatla --- include/uapi/sound/snd_ar_tokens.h | 57 ++++++++++++++++++ sound/soc/qcom/qdsp6/audioreach.c | 94 ++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/audioreach.h | 57 ++++++++++++++++++ sound/soc/qcom/qdsp6/topology.c | 78 +++++++++++++++++++++++++ sound/soc/qcom/sc8280xp.c | 13 +---- 5 files changed, 287 insertions(+), 12 deletions(-) diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index 6b8102eaa121f..dd14d2a88d863 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -168,6 +168,47 @@ enum ar_event_types { * LOG_WAIT = 0, * LOG_IMMEDIATELY = 1 * + * %AR_TKN_U32_MODULE_SYNC_SRC: Frame sync source + * 0 = external, 1 = internal + * + * %AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE: Enable data-out tri-state control + * 0 = disable, 1 = enable + * + * %AR_TKN_U32_MODULE_SLOT_MASK: Active TDM slot bitmask + * + * %AR_TKN_U32_MODULE_NSLOTS_PER_FRAME: Number of slots per TDM frame + * + * %AR_TKN_U32_MODULE_SLOT_WIDTH: Slot width in bits (16 or 32) + * + * %AR_TKN_U32_MODULE_SYNC_MODE: Frame sync mode + * 0 = short pulse, 1 = long pulse + * + * %AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE: Invert frame sync pulse polarity + * 0 = normal, 1 = inverted + * + * %AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY: Data delay relative to frame sync + * 0 = no delay, 1 = one cycle delay + * + * %AR_TKN_U32_MODULE_INTF_MODE: Audio IF interface mode + * AUDIO_IF_INTF_MODE_TDM = 0, + * AUDIO_IF_INTF_MODE_PCM = 1, + * AUDIO_IF_INTF_MODE_I2S = 2 + * + * %AR_TKN_U32_MODULE_QAIF_TYPE: QAIF hardware port type index + * + * %AR_TKN_U32_MODULE_ACTIVE_LANE_MASK: Active lane bitmask for multi-lane + * + * %AR_TKN_U32_MODULE_FRAME_SYNC_RATE: Frame sync rate in Hz + * + * %AR_TKN_U32_MODULE_BIT_CLK_TYPE: Bit clock type + * 0 = internal, 1 = external + * + * %AR_TKN_U32_MODULE_INV_INT_BIT_CLK: Invert internal bit clock + * 0 = normal, 1 = inverted + * + * %AR_TKN_U32_MODULE_INV_EXT_BIT_CLK: Invert external bit clock + * 0 = normal, 1 = inverted + * * %AR_TKN_DAI_INDEX: dai index * */ @@ -240,6 +281,22 @@ enum ar_event_types { #define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260 #define AR_TKN_U32_MODULE_LOG_MODE 261 +#define AR_TKN_U32_MODULE_SYNC_SRC 262 +#define AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE 263 +#define AR_TKN_U32_MODULE_SLOT_MASK 264 +#define AR_TKN_U32_MODULE_NSLOTS_PER_FRAME 265 +#define AR_TKN_U32_MODULE_SLOT_WIDTH 266 +#define AR_TKN_U32_MODULE_SYNC_MODE 267 +#define AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE 268 +#define AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY 269 +#define AR_TKN_U32_MODULE_INTF_MODE 270 +#define AR_TKN_U32_MODULE_QAIF_TYPE 271 +#define AR_TKN_U32_MODULE_ACTIVE_LANE_MASK 272 +#define AR_TKN_U32_MODULE_FRAME_SYNC_RATE 273 +#define AR_TKN_U32_MODULE_BIT_CLK_TYPE 274 +#define AR_TKN_U32_MODULE_INV_INT_BIT_CLK 275 +#define AR_TKN_U32_MODULE_INV_EXT_BIT_CLK 276 + #define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006 struct audioreach_module_priv_data { __le32 size; /* size in bytes of the array, including all elements */ diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index e6e9eb2e85aa1..55bd298bdd744 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -152,6 +152,13 @@ struct apm_i2s_module_intf_cfg { #define APM_I2S_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_i2s_module_intf_cfg), 8) +struct apm_audio_if_module_intf_cfg { + struct apm_module_param_data param_data; + struct param_id_audio_if_intf_cfg cfg; +} __packed; + +#define APM_AUDIO_IF_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_audio_if_module_intf_cfg), 8) + struct apm_module_hw_ep_mf_cfg { struct apm_module_param_data param_data; struct param_id_hw_ep_mf mf; @@ -168,6 +175,13 @@ struct apm_module_frame_size_factor_cfg { #define APM_FS_CFG_PSIZE ALIGN(sizeof(struct apm_module_frame_size_factor_cfg), 8) +struct apm_module_hw_ep_frame_duration_cfg { + struct apm_module_param_data param_data; + struct param_id_hw_ep_frame_duration frame_duration; +} __packed; + +#define APM_HW_EP_FRAME_DURATION_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_frame_duration_cfg), 8) + struct apm_module_hw_ep_power_mode_cfg { struct apm_module_param_data param_data; struct param_id_hw_ep_power_mode_cfg power_mode; @@ -1042,6 +1056,82 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, return q6apm_send_cmd_sync(graph->apm, pkt, 0); } +static int audioreach_audio_if_set_media_format(struct q6apm_graph *graph, + const struct audioreach_module *module, + const struct audioreach_module_config *cfg) +{ + struct apm_module_hw_ep_frame_duration_cfg *fd_cfg; + struct apm_module_param_data *param_data; + struct apm_audio_if_module_intf_cfg *intf_cfg; + struct apm_module_hw_ep_mf_cfg *hw_cfg; + int ic_sz = APM_AUDIO_IF_INTF_CFG_PSIZE; + int ep_sz = APM_HW_EP_CFG_PSIZE; + int fd_sz = APM_HW_EP_FRAME_DURATION_PSIZE; + int size = ic_sz + ep_sz + fd_sz; + u32 slot_mask = cfg->slot_mask ? cfg->slot_mask : module->slot_mask; + u16 nslots_per_frame = cfg->nslots_per_frame ? + (u16)cfg->nslots_per_frame : module->nslots_per_frame; + u16 slot_width = cfg->slot_width ? (u16)cfg->slot_width : module->slot_width; + void *p; + + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + if (IS_ERR(pkt)) + return PTR_ERR(pkt); + + p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; + intf_cfg = p; + + param_data = &intf_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_AUDIO_IF_INTF_CFG; + param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE; + + intf_cfg->cfg.qaif_type = module->qaif_type; + intf_cfg->cfg.intf_idx = (u16)module->hw_interface_idx; + intf_cfg->cfg.intf_mode = module->intf_mode; + intf_cfg->cfg.ctrl_data_out_enable = module->ctrl_data_out_enable; + intf_cfg->cfg.active_slot_mask = slot_mask; + intf_cfg->cfg.nslots_per_frame = nslots_per_frame; + intf_cfg->cfg.slot_width = slot_width; + intf_cfg->cfg.active_lane_mask = module->active_lane_mask; + intf_cfg->cfg.frame_sync_rate = module->frame_sync_rate; + intf_cfg->cfg.frame_sync_src = module->sync_src; + intf_cfg->cfg.frame_sync_mode = module->sync_mode; + intf_cfg->cfg.invert_frame_sync_pulse = module->ctrl_invert_sync_pulse; + intf_cfg->cfg.frame_sync_data_delay = module->ctrl_sync_data_delay; + intf_cfg->cfg.bit_clk_type = module->bit_clk_type; + intf_cfg->cfg.inv_int_bit_clk = module->inv_int_bit_clk; + intf_cfg->cfg.inv_ext_bit_clk = module->inv_ext_bit_clk; + + p += ic_sz; + hw_cfg = p; + param_data = &hw_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_HW_EP_MF_CFG; + param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE; + + hw_cfg->mf.sample_rate = cfg->sample_rate; + hw_cfg->mf.bit_width = cfg->bit_width; + hw_cfg->mf.num_channels = cfg->num_channels; + hw_cfg->mf.data_format = module->data_format; + + p += ep_sz; + fd_cfg = p; + param_data = &fd_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_HW_EP_FRAME_DURATION; + param_data->param_size = fd_sz - APM_MODULE_PARAM_DATA_SIZE; + fd_cfg->frame_duration.frame_duration_in_us = AUDIO_IF_FRAME_DURATION_US; + fd_cfg->frame_duration.allow_frame_duration_normalization = 1; + fd_cfg->frame_duration.min_normalized_frame_dur_us = 1; + fd_cfg->frame_duration.max_normalized_frame_dur_us = 100000; + + return q6apm_send_cmd_sync(graph->apm, pkt, 0); +} + static int audioreach_logging_set_media_format(struct q6apm_graph *graph, const struct audioreach_module *module) { @@ -1377,6 +1467,10 @@ int audioreach_set_media_format(struct q6apm_graph *graph, case MODULE_ID_I2S_SINK: rc = audioreach_i2s_set_media_format(graph, module, cfg); break; + case MODULE_ID_AUDIO_IF_SOURCE: + case MODULE_ID_AUDIO_IF_SINK: + rc = audioreach_audio_if_set_media_format(graph, module, cfg); + break; case MODULE_ID_WR_SHARED_MEM_EP: case MODULE_ID_SH_MEM_PULL_MODE: rc = audioreach_shmem_set_media_format(graph, module, cfg); diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 62a2fd79bbcb9..0adccfdd1fbbe 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -22,6 +22,8 @@ struct q6apm_graph; #define MODULE_ID_PLACEHOLDER_DECODER 0x07001009 #define MODULE_ID_I2S_SINK 0x0700100A #define MODULE_ID_I2S_SOURCE 0x0700100B +#define MODULE_ID_AUDIO_IF_SINK 0x0700117C +#define MODULE_ID_AUDIO_IF_SOURCE 0x0700117D #define MODULE_ID_SAL 0x07001010 #define MODULE_ID_MFC 0x07001015 #define MODULE_ID_DATA_LOGGING 0x0700101A @@ -544,6 +546,41 @@ struct param_id_i2s_intf_cfg { #define PORT_ID_I2S_OUPUT 1 #define I2S_STACK_SIZE 2048 +#define PARAM_ID_AUDIO_IF_INTF_CFG 0x08001B11 + +#define AUDIO_IF_INTF_MODE_TDM 0x0 +#define AUDIO_IF_INTF_MODE_PCM 0x1 +#define AUDIO_IF_INTF_MODE_I2S 0x2 + +struct param_id_audio_if_intf_cfg { + u16 qaif_type; + u16 intf_idx; + u16 intf_mode; + u16 ctrl_data_out_enable; + u32 active_slot_mask; + u16 nslots_per_frame; + u16 slot_width; + u32 active_lane_mask; + u32 frame_sync_rate; + u16 frame_sync_src; + u16 frame_sync_mode; + u16 invert_frame_sync_pulse; + u16 frame_sync_data_delay; + u16 bit_clk_type; + u8 inv_int_bit_clk; + u8 inv_ext_bit_clk; +} __packed; + +#define PARAM_ID_HW_EP_FRAME_DURATION 0x08001B2F +#define AUDIO_IF_FRAME_DURATION_US 1000 + +struct param_id_hw_ep_frame_duration { + u32 frame_duration_in_us; + u32 allow_frame_duration_normalization; + u32 min_normalized_frame_dur_us; + u32 max_normalized_frame_dur_us; +} __packed; + #define PARAM_ID_DISPLAY_PORT_INTF_CFG 0x08001154 struct param_id_display_port_intf_cfg { @@ -877,6 +914,23 @@ struct audioreach_module { uint32_t data_format; uint32_t hw_interface_type; + /* Audio IF module (TDM/PCM/I2S) */ + u16 qaif_type; + u16 sync_src; + u16 ctrl_data_out_enable; + u32 slot_mask; + u16 nslots_per_frame; + u16 slot_width; + u32 active_lane_mask; + u32 frame_sync_rate; + u16 intf_mode; + u16 sync_mode; + u16 ctrl_invert_sync_pulse; + u16 ctrl_sync_data_delay; + u16 bit_clk_type; + u8 inv_int_bit_clk; + u8 inv_ext_bit_clk; + /* PCM module specific */ uint32_t interleave_type; @@ -907,6 +961,9 @@ struct audioreach_module_config { u32 channel_allocation; u32 sd_line_mask; int fmt; + u32 slot_mask; + u16 nslots_per_frame; + u16 slot_width; struct snd_codec codec; u8 channel_map[AR_PCM_MAX_NUM_CHANNEL]; }; diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index 1f69fba6de26d..7faba3bfb6338 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -753,6 +753,80 @@ static int audioreach_widget_i2s_module_load(struct audioreach_module *mod, return 0; } +static int audioreach_widget_audio_if_module_load(struct audioreach_module *mod, + const struct snd_soc_tplg_vendor_array *mod_array) +{ + const struct snd_soc_tplg_vendor_value_elem *mod_elem; + int tkn_count = 0; + + mod_elem = mod_array->value; + + while (tkn_count < le32_to_cpu(mod_array->num_elems)) { + switch (le32_to_cpu(mod_elem->token)) { + case AR_TKN_U32_MODULE_HW_IF_IDX: + mod->hw_interface_idx = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_FMT_DATA: + mod->data_format = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_HW_IF_TYPE: + mod->hw_interface_type = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SYNC_SRC: + mod->sync_src = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE: + mod->ctrl_data_out_enable = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SLOT_MASK: + mod->slot_mask = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_NSLOTS_PER_FRAME: + mod->nslots_per_frame = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SLOT_WIDTH: + mod->slot_width = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INTF_MODE: + mod->intf_mode = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SYNC_MODE: + mod->sync_mode = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE: + mod->ctrl_invert_sync_pulse = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY: + mod->ctrl_sync_data_delay = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_QAIF_TYPE: + mod->qaif_type = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_ACTIVE_LANE_MASK: + mod->active_lane_mask = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_FRAME_SYNC_RATE: + mod->frame_sync_rate = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_BIT_CLK_TYPE: + mod->bit_clk_type = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INV_INT_BIT_CLK: + mod->inv_int_bit_clk = (u8)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INV_EXT_BIT_CLK: + mod->inv_ext_bit_clk = (u8)le32_to_cpu(mod_elem->value); + break; + default: + break; + } + tkn_count++; + mod_elem++; + } + + return 0; +} + static int audioreach_widget_dp_module_load(struct audioreach_module *mod, const struct snd_soc_tplg_vendor_array *mod_array) { @@ -806,6 +880,10 @@ static int audioreach_widget_load_buffer(struct snd_soc_component *component, case MODULE_ID_I2S_SOURCE: audioreach_widget_i2s_module_load(mod, mod_array); break; + case MODULE_ID_AUDIO_IF_SINK: + case MODULE_ID_AUDIO_IF_SOURCE: + audioreach_widget_audio_if_module_load(mod, mod_array); + break; case MODULE_ID_DISPLAY_PORT_SINK: audioreach_widget_dp_module_load(mod, mod_array); break; diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index ccb105aa873dc..ecaaedc5b1a2e 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -224,17 +224,6 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - if (rtd->dai_link->num_codecs) { - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - - snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_CBC_CFC | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_I2S); - - snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, - SND_SOC_CLOCK_IN); - } if (ret < 0 && ret != -EOPNOTSUPP) return ret; @@ -423,4 +412,4 @@ static struct platform_driver snd_sc8280xp_driver = { module_platform_driver(snd_sc8280xp_driver); MODULE_AUTHOR("Srinivas Kandagatla Date: Wed, 3 Jun 2026 13:48:29 +0530 Subject: [PATCH 1017/1058] ASoC: qcom: sc8280xp: add Shikra machine support Register the Shikra machine compatible in the sc8280xp machine driver and include the VA codec DMA TX backend in the capture channel fixup. Signed-off-by: Pratyush Meduri --- sound/soc/qcom/sc8280xp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index ecaaedc5b1a2e..3ada558f9ffeb 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -187,6 +187,7 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = 2; channels->max = 2; switch (cpu_dai->id) { + case VA_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: From 64619609367feb6a382ed3d79a942acd11797849 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Sat, 30 May 2026 13:48:33 +0530 Subject: [PATCH 1018/1058] dt-bindings: sound: qcom,q6apm-dai: add optional qcom,vmid Add an optional qcom,vmid property for q6apm-dais nodes to describe additional VMIDs that should be granted access to PCM DMA buffers. The property is optional and bounded, and driver-side validation will reject invalid values such as including HLOS in the list or VMIDs that exceed 31, matching current SCM source-permission mask handling. Signed-off-by: Ajay Kumar Nandam --- .../devicetree/bindings/sound/qcom,q6apm-dai.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml index 9e5b30d9c6e62..b767625985a74 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml @@ -20,6 +20,16 @@ properties: minItems: 1 maxItems: 2 + qcom,vmid: + description: Optional list of destination VMIDs to share PCM DMA buffers with. + HLOS retains RW access as source owner and must not be listed. + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + minimum: 1 + maximum: 31 + minItems: 1 + maxItems: 8 + required: - compatible - iommus From 8fa99335a90c747bf369ac52adb16bb65c73ada0 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Sat, 30 May 2026 13:48:33 +0530 Subject: [PATCH 1019/1058] ASoC: qcom: q6apm-dai: add VMID-based SCM assignment Add optional VMID-based SCM memory assignment for q6apm PCM DMA buffers when qcom,vmid is provided in DT. On platforms where audio processing runs outside HLOS, LPASS PCM DMA buffers must be shared with secure/non-HLOS VMIDs so both endpoints can access the same payload memory. Keep HLOS as an RW owner and grant configured destination VMIDs RW access so both playback and capture data paths remain functional. Track SCM assignment state per substream, unwind assignments in hw_free and close paths, validate qcom,vmid values in probe, and fail hw_params() if stale assignment release fails. Select QCOM_SCM so direct qcom_scm_assign_mem() and qcom_scm_is_available() calls are dependency-safe for built-in and modular combinations. Use qcom_scm_assign_mem() return handling directly in unassign paths, limit accepted VMIDs to 31 to match current SCM source-permission mask handling, and keep assignment state on unassign failure so retries in the same stream lifetime can recover. Signed-off-by: Ajay Kumar Nandam --- sound/soc/qcom/Kconfig | 1 + sound/soc/qcom/qdsp6/q6apm-dai.c | 222 +++++++++++++++++++++++++++++-- 2 files changed, 215 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 008b5ccae331a..a43f3fa7f4b77 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -111,6 +111,7 @@ config SND_SOC_QDSP6_ASM_DAI config SND_SOC_QDSP6_APM_DAI tristate + select QCOM_SCM select SND_SOC_COMPRESS config SND_SOC_QDSP6_APM_LPASS_DAI diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index bf1f872a09f45..cccb6444ddf5c 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "q6apm.h" @@ -34,6 +35,8 @@ #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) +#define Q6APM_MAX_VMIDS 8 +#define Q6APM_SCM_MAX_VMID 31 #define SID_MASK_DEFAULT 0xF static const struct snd_compr_codec_caps q6apm_compr_caps = { @@ -67,16 +70,21 @@ struct q6apm_dai_rtd { uint32_t last_pos_index; phys_addr_t phys; phys_addr_t pos_phys; + phys_addr_t dma_addr; + bool dma_addr_valid; unsigned int pcm_size; unsigned int push_pull_size; unsigned int pcm_count; unsigned int periods; + unsigned int scm_size; uint64_t bytes_sent; uint64_t bytes_received; uint64_t copied_total; uint16_t bits_per_sample; snd_pcm_uframes_t queue_ptr; bool next_track; + bool scm_assigned; + u64 scm_src_perms; enum stream_state state; struct q6apm_graph *graph; spinlock_t lock; @@ -85,8 +93,93 @@ struct q6apm_dai_rtd { struct q6apm_dai_data { long long sid; + int num_vmids; + u32 vmids[Q6APM_MAX_VMIDS]; + bool use_scm_assign; }; +static int q6apm_dai_assign_memory(struct q6apm_dai_rtd *prtd, + const struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + int dst_count = 0; + int ret; + int i; + + if (!pdata->use_scm_assign || pdata->num_vmids <= 0 || prtd->scm_assigned) + return 0; + + /* hw_params() validates and sets dma_addr_valid before prepare(). */ + if (!prtd->dma_addr_valid || !prtd->pcm_size) + return -EINVAL; + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + /* Always keep HLOS RW so CPU can continue buffer access. */ + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + /* + * Probe-time validation rejects HLOS in qcom,vmid, so this is + * only a defensive check for future non-DT vmids[] population. + */ + if (WARN_ON_ONCE(pdata->vmids[i] == QCOM_SCM_VMID_HLOS)) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + + /* Nothing to assign beyond HLOS access. */ + if (dst_count == 1) { + kfree(dst_vmids); + return 0; + } + + prtd->scm_size = ALIGN(prtd->pcm_size, PAGE_SIZE); + prtd->scm_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + + ret = qcom_scm_assign_mem(prtd->dma_addr, prtd->scm_size, + &prtd->scm_src_perms, dst_vmids, dst_count); + kfree(dst_vmids); + if (ret) + return ret; + + prtd->scm_assigned = true; + return 0; +} + +static int q6apm_dai_unassign_memory(struct q6apm_dai_rtd *prtd, + const struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = prtd->substream->pcm->card->dev; + int ret; + + if (!pdata->use_scm_assign || !prtd->scm_assigned) + return 0; + + ret = qcom_scm_assign_mem(prtd->dma_addr, prtd->scm_size, + &prtd->scm_src_perms, &hlos, 1); + if (!ret) { + prtd->scm_assigned = false; + prtd->scm_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + } else { + dev_err(dev, "Failed to unassign DMA buffer %pa from VMIDs: %d\n", + &prtd->dma_addr, ret); + } + + return ret; +} + static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | @@ -219,6 +312,7 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, struct audioreach_module_config cfg; struct device *dev = component->dev; struct q6apm_dai_data *pdata; + bool assigned_now = false; int ret; pdata = snd_soc_component_get_drvdata(component); @@ -244,13 +338,20 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->last_pos_index = 0; prtd->pcm_count = snd_pcm_lib_period_bytes(substream); + if (!prtd->scm_assigned) { + ret = q6apm_dai_assign_memory(prtd, pdata); + if (ret) + return ret; + assigned_now = prtd->scm_assigned; + } + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) { if (prtd->pcm_size != prtd->push_pull_size) { ret = q6apm_push_pull_config(prtd->graph, prtd->phys, prtd->pos_phys, prtd->pcm_size); if (ret < 0) { dev_err(dev, "Push/Pull config failed rc = %d\n", ret); - return ret; + goto err_unassign; } ret = q6apm_register_watermark_event(prtd->graph, @@ -258,7 +359,7 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->periods); if (ret < 0) { dev_err(dev, "WaterMark event config failed rc = %d\n", ret); - return ret; + goto err_unassign; } prtd->push_pull_size = prtd->pcm_size; } @@ -267,34 +368,33 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, (prtd->pcm_size / prtd->periods), prtd->periods); if (ret < 0) { dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); - return ret; + goto err_unassign; } - } ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); if (ret < 0) { dev_err(dev, "%s: CMD Format block failed\n", __func__); - return ret; + goto err_unassign; } /* rate and channels are sent to audio driver */ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); if (ret < 0) { dev_err(dev, "Failed to set media format %d\n", ret); - return ret; + goto err_unassign; } ret = q6apm_graph_prepare(prtd->graph); if (ret) { dev_err(dev, "Failed to prepare Graph %d\n", ret); - return ret; + goto err_unassign; } ret = q6apm_graph_start(prtd->graph); if (ret) { dev_err(dev, "Failed to Start Graph %d\n", ret); - return ret; + goto err_unassign; } if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) { if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -309,6 +409,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->state = Q6APM_STREAM_RUNNING; return 0; + +err_unassign: + if (assigned_now) + q6apm_dai_unassign_memory(prtd, pdata); + + return ret; } static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) @@ -432,6 +538,9 @@ static int q6apm_dai_open(struct snd_soc_component *component, runtime->private_data = prtd; runtime->dma_bytes = BUFFER_BYTES_MAX; + prtd->scm_assigned = false; + prtd->dma_addr_valid = false; + prtd->dma_addr = substream->dma_buffer.addr; if (pdata->sid < 0) prtd->phys = substream->dma_buffer.addr; else @@ -456,13 +565,25 @@ static int q6apm_dai_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); struct q6apm_dai_rtd *prtd = runtime->private_data; + int ret; if (prtd->state) { /* only stop graph that is started */ q6apm_graph_stop(prtd->graph); q6apm_free_fragments(prtd->graph, substream->stream); } + if (pdata && prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) { + dev_warn(component->dev, + "close(): VMID unassign failed for DMA buffer %pa: %d\n", + &prtd->dma_addr, ret); + WARN_ONCE(1, "q6apm-dai: SCM VMID unassign leak for DMA buffer %pa\n", + &prtd->dma_addr); + } + } q6apm_graph_close(prtd->graph); prtd->graph = NULL; @@ -511,6 +632,27 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); + int ret; + + if (!pdata) + return -EINVAL; + + if (prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) { + dev_warn(component->dev, + "hw_params(): failed to release previous VMID assignment: %d\n", + ret); + return ret; + } + } + + if (!substream->dma_buffer.addr) + return -ENOMEM; + + prtd->dma_addr = substream->dma_buffer.addr; + prtd->dma_addr_valid = true; prtd->pcm_size = params_buffer_bytes(params); prtd->periods = params_periods(params); @@ -529,6 +671,27 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, return 0; } +static int q6apm_dai_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); + struct q6apm_dai_rtd *prtd = substream->runtime->private_data; + int ret; + + if (pdata && prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) + dev_warn(component->dev, + "hw_free(): VMID unassign failed for DMA buffer %pa: %d\n", + &prtd->dma_addr, ret); + } + + /* Fixed PCM DMA buffer is released in pcm_free(); close() retries unassign. */ + prtd->dma_addr_valid = false; + + return 0; +} + static int q6apm_dai_memory_map(struct snd_soc_component *component, struct snd_pcm_substream *substream, int graph_id, bool is_push_pull) @@ -1006,6 +1169,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { .open = q6apm_dai_open, .close = q6apm_dai_close, .prepare = q6apm_dai_prepare, + .hw_free = q6apm_dai_hw_free, .pcm_new = q6apm_dai_pcm_new, .pcm_free = q6apm_dai_pcm_free, .hw_params = q6apm_dai_hw_params, @@ -1023,6 +1187,7 @@ static int q6apm_dai_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; struct q6apm_dai_data *pdata; struct of_phandle_args args; + int vmids; int rc; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -1035,6 +1200,47 @@ static int q6apm_dai_probe(struct platform_device *pdev) else pdata->sid = args.args[0] & SID_MASK_DEFAULT; + vmids = of_property_count_u32_elems(node, "qcom,vmid"); + if (vmids == -EINVAL) { + pdata->num_vmids = 0; + pdata->use_scm_assign = false; + } else if (vmids < 0) { + return vmids; + } else if (vmids == 0) { + dev_err(dev, "qcom,vmid must contain at least one VMID\n"); + return -EINVAL; + } else if (vmids > Q6APM_MAX_VMIDS) { + dev_err(dev, "qcom,vmid: %d VMIDs exceeds maximum of %d\n", + vmids, Q6APM_MAX_VMIDS); + return -EINVAL; + } + + if (vmids > 0) { + int i; + + rc = of_property_read_u32_array(node, "qcom,vmid", + pdata->vmids, vmids); + if (rc) + return rc; + for (i = 0; i < vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) { + dev_err(dev, "qcom,vmid must not include HLOS VMID (%u)\n", + QCOM_SCM_VMID_HLOS); + return -EINVAL; + } + if (pdata->vmids[i] > Q6APM_SCM_MAX_VMID) { + dev_err(dev, "qcom,vmid[%d]=%u exceeds SCM max VMID %u\n", + i, pdata->vmids[i], Q6APM_SCM_MAX_VMID); + return -EINVAL; + } + } + pdata->num_vmids = vmids; + pdata->use_scm_assign = true; + } + + if (pdata->use_scm_assign && !qcom_scm_is_available()) + return -EPROBE_DEFER; + dev_set_drvdata(dev, pdata); return devm_snd_soc_register_component(dev, &q6apm_fe_dai_component, NULL, 0); From 34b85ac3d0d626449f722268b29092eaf09a8765 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Thu, 4 Jun 2026 11:05:48 +0530 Subject: [PATCH 1020/1058] dt-bindings: sound: qcom,wsa885x-i2c: add prefixed properties Document the qcom,wsa885x-init-table and qcom,battery-config property names while keeping the existing init table and qcom,battery_config properties for compatibility. Mark qcom,battery_config deprecated and make the init table optional so boards can rely on codec register defaults. Signed-off-by: Pratyush Meduri --- .../devicetree/bindings/sound/qcom,wsa885x-i2c.yaml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml index 6bc742b0aacf8..69af511a400ea 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml @@ -42,23 +42,34 @@ properties: description: 1.8V analog/digital core supply. qcom,battery_config: + deprecated: true description: Battery topology configuration. $ref: /schemas/types.yaml#/definitions/uint32 enum: [1, 2] + qcom,battery-config: + description: Speaker battery configuration, 1 for 1S and 2S. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2] + wsa885x-init-table: description: Register/value initialization table as pairs. $ref: /schemas/types.yaml#/definitions/uint32-array minItems: 2 maxItems: 512 + qcom,wsa885x-init-table: + description: Register/value initialization table as pairs. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 256 + required: - compatible - reg - '#sound-dai-cells' - vdd-io-supply - vdd-1p8-supply - - wsa885x-init-table unevaluatedProperties: false From 6a717add972ae7c7c2a5e1ba11121c39d5a3900e Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Thu, 4 Jun 2026 11:05:48 +0530 Subject: [PATCH 1021/1058] ASoC: codecs: wsa885x-i2c: support prefixed DT properties Accept the qcom,wsa885x-init-table and qcom,battery-config property names used by downstream Shikra audio device trees while keeping compatibility with the existing unprefixed init table and qcom,battery_config properties. Allow the init table to be absent and rely on register defaults, matching the downstream codec-driver behavior. Validate the battery configuration value when provided. Signed-off-by: Pratyush Meduri --- sound/soc/codecs/wsa885x-i2c.c | 61 ++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/wsa885x-i2c.c b/sound/soc/codecs/wsa885x-i2c.c index 1d40761106177..ac2d464b9742d 100644 --- a/sound/soc/codecs/wsa885x-i2c.c +++ b/sound/soc/codecs/wsa885x-i2c.c @@ -1321,7 +1321,7 @@ static int wsa885x_i2c_probe(struct i2c_client *client) { struct wsa885x_i2c_priv *wsa885x; const char *init_table_prop = "wsa885x-init-table"; - int ret, i; + int ret, i, count; struct device *dev = &client->dev; wsa885x = devm_kzalloc(&client->dev, sizeof(struct wsa885x_i2c_priv), @@ -1338,39 +1338,50 @@ static int wsa885x_i2c_probe(struct i2c_client *client) if (IS_ERR(wsa885x->regmap)) return PTR_ERR(wsa885x->regmap); - wsa885x->init_table_size = - of_property_count_u32_elems(dev->of_node, init_table_prop); - - if (wsa885x->init_table_size <= 0) { - dev_err(dev, "%s: Failed to count elements from %s\n", - __func__, init_table_prop); - return -EINVAL; - } + count = of_property_count_u32_elems(dev->of_node, + "qcom,wsa885x-init-table"); + if (count > 0) + init_table_prop = "qcom,wsa885x-init-table"; + else + count = of_property_count_u32_elems(dev->of_node, init_table_prop); - if (wsa885x->init_table_size % 2 != 0) { - dev_err(dev, "%s: Invalid number of elements in %s\n", + if (count > 0) { + if (count % 2 != 0) { + dev_err(dev, "%s: Invalid number of elements in %s\n", __func__, init_table_prop); - return -EINVAL; - } + return -EINVAL; + } - wsa885x->init_table = devm_kzalloc( - dev, wsa885x->init_table_size * sizeof(u32), GFP_KERNEL); - if (!wsa885x->init_table) - return -ENOMEM; + wsa885x->init_table_size = count; + wsa885x->init_table = devm_kcalloc(dev, wsa885x->init_table_size, + sizeof(*wsa885x->init_table), + GFP_KERNEL); + if (!wsa885x->init_table) + return -ENOMEM; - if (of_property_read_u32_array(dev->of_node, init_table_prop, - wsa885x->init_table, - wsa885x->init_table_size)) { - dev_err(dev, - "%s: Failed to read %s\n", + if (of_property_read_u32_array(dev->of_node, init_table_prop, wsa885x->init_table, + wsa885x->init_table_size)) { + dev_err(dev, "%s: Failed to read %s\n", __func__, init_table_prop); - return -EINVAL; + return -EINVAL; + } + } else { + dev_dbg(dev, "%s: init table absent, relying on reg_defaults\n", + __func__); } - ret = of_property_read_u32(dev->of_node, "qcom,battery_config", &wsa885x->batt_conf); + ret = of_property_read_u32(dev->of_node, "qcom,battery-config", + &wsa885x->batt_conf); + if (ret) + ret = of_property_read_u32(dev->of_node, "qcom,battery_config", + &wsa885x->batt_conf); if (ret) { - dev_err(dev, "battery_config not specified, 1S is default: %d\n", ret); + dev_dbg(dev, "battery-config not specified, defaulting to 1S\n"); wsa885x->batt_conf = batt_1s; + } else if (wsa885x->batt_conf != batt_1s && wsa885x->batt_conf != batt_2s) { + return dev_err_probe(dev, -EINVAL, + "Invalid battery-config value %u (expected 1 or 2)\n", + wsa885x->batt_conf); } for (i = 0; i < SUPPLIES_NUM; i++) From 6ec78bc2015e99219f77e4be7de4eccefff31e46 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Fri, 3 Jul 2026 13:28:15 +0530 Subject: [PATCH 1022/1058] ASoC: qcom: qdsp6: generalize GPR service domain Use each GPR domain advertised by the qcom APR/GPR layer when building APM/PRM packets and add explicit dest_domain parameters to all AudioReach alloc helpers. Legacy helpers fall back to ADSP while graphs, media-format, and shared-memory packets reuse gdev->domain_id for modem targets. Note: audioreach_audio_if_set_media_format() (QAIF support) is not included as it depends on QAIF infrastructure not yet in mainline. Signed-off-by: Pratyush Meduri --- arch/arm64/configs/defconfig | 1 + sound/soc/qcom/qdsp6/audioreach.c | 119 ++++++++++++++++------ sound/soc/qcom/qdsp6/audioreach.h | 24 +++-- sound/soc/qcom/qdsp6/q6apm.c | 47 ++++++--- sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c | 2 +- sound/soc/qcom/qdsp6/q6prm.c | 19 ++-- 6 files changed, 146 insertions(+), 66 deletions(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 066b854b3f973..e04acb1c4f300 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -108,6 +108,7 @@ CONFIG_ARM_IMX_CPUFREQ_DT=m CONFIG_ARM_MEDIATEK_CPUFREQ=y CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y CONFIG_ARM_QCOM_CPUFREQ_HW=y +CONFIG_CLK_SHIKRA_AUDIOCORECC=m CONFIG_ARM_RASPBERRYPI_CPUFREQ=m CONFIG_ARM_SCMI_CPUFREQ=y CONFIG_ARM_TEGRA186_CPUFREQ=y diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index 55bd298bdd744..b4b082ba87b93 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -241,8 +241,9 @@ struct apm_module_sp_vi_channel_map_cfg { sizeof(struct apm_module_sp_vi_channel_map_cfg) + \ (ch) * sizeof(uint32_t), 8) -static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) +static void *__audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain, + bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -262,7 +263,10 @@ static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + if (!dest_domain) + dest_domain = GPR_DOMAIN_ID_ADSP; + + pkt->hdr.dest_domain = dest_domain; pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -278,31 +282,35 @@ static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t return pkt; } -void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port) +void *audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain) { - return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, false); + return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, + dest_domain, false); } EXPORT_SYMBOL_GPL(audioreach_alloc_pkt); -void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, uint32_t src_port) +void *audioreach_alloc_apm_pkt(int pkt_size, u32 opcode, u32 token, + u32 src_port, u16 dest_domain) { return __audioreach_alloc_pkt(pkt_size, opcode, token, src_port, APM_MODULE_INSTANCE_ID, - false); + dest_domain, false); } EXPORT_SYMBOL_GPL(audioreach_alloc_apm_pkt); -void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port) +void *audioreach_alloc_cmd_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain) { - return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true); + return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, + dest_domain, true); } EXPORT_SYMBOL_GPL(audioreach_alloc_cmd_pkt); -void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token) +void *audioreach_alloc_apm_cmd_pkt(int pkt_size, u32 opcode, u32 token, + u16 dest_domain) { return __audioreach_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID, - APM_MODULE_INSTANCE_ID, true); + APM_MODULE_INSTANCE_ID, dest_domain, true); } EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt); @@ -499,6 +507,7 @@ void *audioreach_alloc_graph_pkt(struct q6apm *apm, int num_sub_graphs = 0; int num_modules = 0; int num_modules_list; + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); struct gpr_pkt *pkt; void *p; @@ -533,7 +542,8 @@ void *audioreach_alloc_graph_pkt(struct q6apm *apm, mc_sz = APM_MOD_CONN_PSIZE(mcon, num_connections); payload_size = sg_sz + cont_sz + ml_sz + mp_sz + mc_sz; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0, + dest_domain); if (IS_ERR(pkt)) return pkt; @@ -659,7 +669,10 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -718,7 +731,10 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz + pm_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -778,7 +794,10 @@ int audioreach_send_u32_param(struct q6apm_graph *graph, int payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return -ENOMEM; @@ -834,7 +853,10 @@ static int audioreach_set_module_config(struct q6apm_graph *graph, int size = le32_to_cpu(module->data->size); void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -857,7 +879,10 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, int i; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -972,9 +997,12 @@ int audioreach_compr_set_param(struct q6apm_graph *graph, int iid = graph->shm_iid; int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, - DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, - 0, graph->port->id, iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_cmd_pkt(payload_size, + DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, + 0, graph->port->id, iid, + dest_domain); if (IS_ERR(pkt)) return -ENOMEM; @@ -1002,7 +1030,10 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1140,7 +1171,10 @@ static int audioreach_logging_set_media_format(struct q6apm_graph *graph, int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1178,8 +1212,10 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, payload_size = APM_PCM_MODULE_FMT_CMD_PSIZE(num_channels); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1221,8 +1257,10 @@ int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int nu payload_size = sizeof(*event) + sizeof(*level) + num_levels * sizeof(uint32_t); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_REGISTER_MODULE_EVENTS, 0, - graph->port->id, graph->shm_iid); + graph->port->id, graph->shm_iid, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1262,9 +1300,11 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, payload_size = APM_SHMEM_FMT_CFG_PSIZE(num_channels) + APM_MODULE_PARAM_DATA_SIZE; + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, - graph->port->id, module->instance_id); + graph->port->id, module->instance_id, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1309,7 +1349,10 @@ int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct apm_module_param_data *param_data; int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1334,7 +1377,10 @@ static int audioreach_gain_set(struct q6apm_graph *graph, struct apm_module_param_data *param_data; struct apm_gain_module_cfg *cfg; int size = APM_GAIN_CFG_PSIZE; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1370,6 +1416,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, int op_sz, cm_sz, ex_sz; struct apm_module_param_data *param_data; int rc, i, payload_size; + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt; void *p; @@ -1385,7 +1432,8 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, payload_size = op_sz + cm_sz + ex_sz; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1543,7 +1591,8 @@ int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys, void *p; payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1574,8 +1623,12 @@ int audioreach_shared_memory_send_eos(struct q6apm_graph *graph) { struct data_cmd_wr_sh_mem_ep_eos *eos; int iid = graph->shm_iid; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos), - DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_cmd_pkt(sizeof(*eos), + DATA_CMD_WR_SH_MEM_EP_EOS, 0, + graph->port->id, iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 0adccfdd1fbbe..79c28bbe1a690 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -2,6 +2,7 @@ #ifndef __AUDIOREACH_H__ #define __AUDIOREACH_H__ +#include #include #include #include @@ -969,17 +970,20 @@ struct audioreach_module_config { }; /* Packet Allocation routines */ -void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t - token); +static inline u16 audioreach_gpr_dest_domain(gpr_device_t *gdev) +{ + return gdev && gdev->domain_id ? gdev->domain_id : GPR_DOMAIN_ID_ADSP; +} + +void *audioreach_alloc_apm_cmd_pkt(int pkt_size, u32 opcode, u32 token, + u16 dest_domain); void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels); -void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, - uint32_t token, uint32_t src_port, - uint32_t dest_port); -void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, - uint32_t src_port); -void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, - uint32_t token, uint32_t src_port, - uint32_t dest_port); +void *audioreach_alloc_cmd_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain); +void *audioreach_alloc_apm_pkt(int pkt_size, u32 opcode, u32 token, + u32 src_port, u16 dest_domain); +void *audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain); void *audioreach_alloc_graph_pkt(struct q6apm *apm, const struct audioreach_graph_info *info); /* Topology specific */ diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 641d6d2432299..a65d6793353a4 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -102,7 +102,10 @@ static int audioreach_graph_mgmt_cmd(struct audioreach_graph *graph, uint32_t op struct q6apm *apm = graph->apm; int i = 0, payload_size = APM_GRAPH_MGMT_PSIZE(mgmt_cmd, num_sub_graphs); - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -142,8 +145,10 @@ static void q6apm_put_audioreach_graph(struct kref *ref) static int q6apm_get_apm_state(struct q6apm *apm) { - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(0, - APM_CMD_GET_SPF_STATE, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(0, APM_CMD_GET_SPF_STATE, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -216,8 +221,11 @@ static int __q6apm_map_memory_fixed_region(struct device *dev, unsigned int grap uint32_t buf_sz; void *p; uint32_t pos_mask = is_pos_buf ? APM_MMAP_TOKEN_MAP_TYPE_POS_BUF : 0; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, - APM_CMD_SHARED_MEM_MAP_REGIONS, (graph_id | pos_mask)); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, + APM_CMD_SHARED_MEM_MAP_REGIONS, + graph_id | pos_mask, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -326,8 +334,11 @@ static int __q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int gr struct q6apm *apm = dev_get_drvdata(dev->parent); struct audioreach_graph_info *info; uint32_t mem_map_handle; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd), - APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(sizeof(*cmd), + APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -475,10 +486,14 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2 *write_buffer; struct audio_buffer *ab; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*write_buffer), - DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, - graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT), - graph->port->id, graph->shm_iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_pkt(sizeof(*write_buffer), + DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, + graph->rx_data.dsp_buf | + (len << APM_WRITE_TOKEN_LEN_SHIFT), + graph->port->id, graph->shm_iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -512,9 +527,13 @@ int q6apm_read(struct q6apm_graph *graph) struct audioreach_graph_data *port; struct audio_buffer *ab; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*read_buffer), - DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, - graph->tx_data.dsp_buf, graph->port->id, graph->shm_iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_pkt(sizeof(*read_buffer), + DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, + graph->tx_data.dsp_buf, + graph->port->id, graph->shm_iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c index 03838582aeade..7bb4383fcb35a 100644 --- a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c +++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c @@ -12,7 +12,7 @@ #include #include "q6dsp-lpass-clocks.h" -#define Q6DSP_MAX_CLK_ID 104 +#define Q6DSP_MAX_CLK_ID 132 #define Q6DSP_LPASS_CLK_ROOT_DEFAULT 0 diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c index 04892fb4423fe..15ca51ce33b80 100644 --- a/sound/soc/qcom/qdsp6/q6prm.c +++ b/sound/soc/qcom/qdsp6/q6prm.c @@ -71,8 +71,9 @@ static int q6prm_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool rsp_opcode = PRM_CMD_RSP_RELEASE_HW_RSC; } - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*req), opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*req), + opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -112,9 +113,10 @@ static int q6prm_request_lpass_clock(struct device *dev, int clk_id, int clk_att struct prm_cmd_request_rsc *req; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, - gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*req), + PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, + GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -144,9 +146,10 @@ static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_att struct prm_cmd_release_rsc *rel; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, - gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*rel), + PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, + GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); From 8dbc5e357819e828f1cb3d6801175b5c83982228 Mon Sep 17 00:00:00 2001 From: Murali Krishna Date: Tue, 9 Jun 2026 15:02:58 +0530 Subject: [PATCH 1023/1058] dt-bindings: qcom,shikra-epss-l3: remove the SoC specific bindings EPSS L3 hardware on Shikra SoC is similar to EPSS/OSM L3 hardware on other Qualcomm SoCs. Use the existing qcom,osm-l3 bindings to describe it. Signed-off-by: Murali Krishna --- .../interconnect/qcom,shikra-epss-l3.yaml | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml diff --git a/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml deleted file mode 100644 index 9cb68a90fa5e1..0000000000000 --- a/Documentation/devicetree/bindings/interconnect/qcom,shikra-epss-l3.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/interconnect/qcom,shikra-epss-l3.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm Operating State Manager (OSM) L3 Shikra Interconnect Provider - -maintainers: - - Raviteja Laggyshetty - -description: - L3 cache bandwidth requirements on Qualcomm SoCs is serviced by the OSM. - The OSM L3 interconnect provider aggregates the L3 bandwidth requests - from CPU/GPU and relays it to the OSM. - -properties: - compatible: - enum: - - qcom,shikra-epss-l3 - - reg: - maxItems: 1 - - clocks: - items: - - description: xo clock - - description: alternate clock - - clock-names: - items: - - const: xo - - const: alternate - - '#interconnect-cells': - const: 1 - -required: - - compatible - - reg - - clocks - - clock-names - - '#interconnect-cells' - -additionalProperties: false - -examples: - - | - - #define GPLL0 165 - #define RPMH_CXO_CLK 0 - - epss_l3: interconnect@fd90000 { - compatible = "qcom,shikra-epss-l3"; - reg = <0xfd90000 0x1000>; - - clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; - clock-names = "xo", "alternate"; - - #interconnect-cells = <1>; - }; From 25924d70d6983e9f4f4d086d9f5b83f1fb67a811 Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Wed, 3 Jun 2026 11:26:12 +0000 Subject: [PATCH 1024/1058] dt-bindings: interconnect: qcom,osm-l3: Add EPSS L3 DT binding for Qualcomm Shikra SoC Document the EPSS L3 interconnect provider binding for Qualcomm Shikra SoC. The Shikra EPSS L3 block is similar to existing Qualcomm EPSS/OSM L3 providers, but supports only up to 12 frequency lookup table entries. Co-developed-by: Odelu Kukatla Signed-off-by: Odelu Kukatla Signed-off-by: Raviteja Laggyshetty Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260603-shikra_epss_l3-v3-1-3c2e0b796e78@oss.qualcomm.com --- Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml index 41b9f758bf8b8..3b8ebe17a9760 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml @@ -17,6 +17,8 @@ description: properties: compatible: oneOf: + - enum: + - qcom,shikra-epss-l3 - items: - enum: - qcom,sc7180-osm-l3 From 1d0ca8f8806ed43d85e38b35789b0f7fb68ca2c1 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 8 Jun 2026 17:42:07 +0530 Subject: [PATCH 1025/1058] dt-bindings: clock: qcom,rpmcc: Update Qualcomm Shikra SoC RPMCC The Qualcomm Shikra RPMCC has the clocks same as Agatti (QCM2290) RPMCC. Hence, add support to use the QCM2290 RPMCC compatible as fallback for Shikra RPMCC. Signed-off-by: Imran Shaik --- .../devicetree/bindings/clock/qcom,rpmcc.yaml | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml index 06f8439bb032a..af9fc5b14a810 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml @@ -21,36 +21,41 @@ description: | properties: compatible: - items: - - enum: - - qcom,rpmcc-apq8060 - - qcom,rpmcc-apq8064 - - qcom,rpmcc-ipq806x - - qcom,rpmcc-mdm9607 - - qcom,rpmcc-msm8226 - - qcom,rpmcc-msm8660 - - qcom,rpmcc-msm8909 - - qcom,rpmcc-msm8916 - - qcom,rpmcc-msm8917 - - qcom,rpmcc-msm8936 - - qcom,rpmcc-msm8937 - - qcom,rpmcc-msm8940 - - qcom,rpmcc-msm8953 - - qcom,rpmcc-msm8974 - - qcom,rpmcc-msm8976 - - qcom,rpmcc-msm8992 - - qcom,rpmcc-msm8994 - - qcom,rpmcc-msm8996 - - qcom,rpmcc-msm8998 - - qcom,rpmcc-qcm2290 - - qcom,rpmcc-qcs404 - - qcom,rpmcc-sdm429 - - qcom,rpmcc-sdm660 - - qcom,rpmcc-shikra - - qcom,rpmcc-sm6115 - - qcom,rpmcc-sm6125 - - qcom,rpmcc-sm6375 - - const: qcom,rpmcc + oneOf: + - items: + - enum: + - qcom,rpmcc-apq8060 + - qcom,rpmcc-apq8064 + - qcom,rpmcc-ipq806x + - qcom,rpmcc-mdm9607 + - qcom,rpmcc-msm8226 + - qcom,rpmcc-msm8660 + - qcom,rpmcc-msm8909 + - qcom,rpmcc-msm8916 + - qcom,rpmcc-msm8917 + - qcom,rpmcc-msm8936 + - qcom,rpmcc-msm8937 + - qcom,rpmcc-msm8940 + - qcom,rpmcc-msm8953 + - qcom,rpmcc-msm8974 + - qcom,rpmcc-msm8976 + - qcom,rpmcc-msm8992 + - qcom,rpmcc-msm8994 + - qcom,rpmcc-msm8996 + - qcom,rpmcc-msm8998 + - qcom,rpmcc-qcm2290 + - qcom,rpmcc-qcs404 + - qcom,rpmcc-sdm429 + - qcom,rpmcc-sdm660 + - qcom,rpmcc-sm6115 + - qcom,rpmcc-sm6125 + - qcom,rpmcc-sm6375 + - const: qcom,rpmcc + - items: + - enum: + - qcom,rpmcc-shikra + - const: qcom,rpmcc-qcm2290 + - const: qcom,rpmcc '#clock-cells': const: 1 @@ -127,6 +132,7 @@ allOf: - qcom,rpmcc-qcs404 - qcom,rpmcc-sdm429 - qcom,rpmcc-sdm660 + - qcom,rpmcc-shikra - qcom,rpmcc-sm6115 - qcom,rpmcc-sm6125 From 466b88bed442cd754ace063dba7186c3c2d50347 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 8 Jun 2026 17:43:25 +0530 Subject: [PATCH 1026/1058] clk: qcom: smd-rpm: Add missing RF_CLK1/RF_CLK2 clocks support on Agatti Add support for missing RF_CLK1/RF_CLK2 clocks on Qualcomm Agatti (QCM2290) SoC. Drop the Shikra specific clock table since it matches QCM2290 RPMCC and can be handled via DT compatible fallback. Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-smd-rpm.c | 44 ++++------------------------------ 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 50daa2b0b8235..0b624ed4715c7 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -495,6 +495,7 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(rf_clk2, 5, 19200000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(rf_clk3, 6, 19200000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(ln_bb_clk, 8, 19200000); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PREFIX(38m4_, rf_clk2, 5, 38400000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PREFIX(38m4_, rf_clk3, 6, 38400000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(cxo_d0, 1, 19200000); @@ -1262,6 +1263,10 @@ static struct clk_smd_rpm *qcm2290_clks[] = { [RPM_SMD_QDSS_A_CLK] = &clk_smd_rpm_branch_qdss_a_clk, [RPM_SMD_LN_BB_CLK2] = &clk_smd_rpm_ln_bb_clk2, [RPM_SMD_LN_BB_CLK2_A] = &clk_smd_rpm_ln_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &clk_smd_rpm_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &clk_smd_rpm_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &clk_smd_rpm_38m4_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &clk_smd_rpm_38m4_rf_clk2_a, [RPM_SMD_RF_CLK3] = &clk_smd_rpm_38m4_rf_clk3, [RPM_SMD_RF_CLK3_A] = &clk_smd_rpm_38m4_rf_clk3_a, [RPM_SMD_IPA_CLK] = &clk_smd_rpm_ipa_clk, @@ -1289,44 +1294,6 @@ static const struct rpm_smd_clk_desc rpm_clk_qcm2290 = { .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) }; -static struct clk_smd_rpm *shikra_clks[] = { - [RPM_SMD_XO_CLK_SRC] = &clk_smd_rpm_branch_bi_tcxo, - [RPM_SMD_XO_A_CLK_SRC] = &clk_smd_rpm_branch_bi_tcxo_a, - [RPM_SMD_QDSS_CLK] = &clk_smd_rpm_branch_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &clk_smd_rpm_branch_qdss_a_clk, - [RPM_SMD_LN_BB_CLK2] = &clk_smd_rpm_ln_bb_clk2, - [RPM_SMD_LN_BB_CLK2_A] = &clk_smd_rpm_ln_bb_clk2_a, - [RPM_SMD_RF_CLK1] = &clk_smd_rpm_rf_clk1, - [RPM_SMD_RF_CLK1_A]= &clk_smd_rpm_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &clk_smd_rpm_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &clk_smd_rpm_rf_clk2_a, - [RPM_SMD_RF_CLK3] = &clk_smd_rpm_38m4_rf_clk3, - [RPM_SMD_RF_CLK3_A] = &clk_smd_rpm_38m4_rf_clk3_a, - [RPM_SMD_IPA_CLK] = &clk_smd_rpm_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &clk_smd_rpm_ipa_a_clk, - [RPM_SMD_SNOC_PERIPH_CLK] = &clk_smd_rpm_bus_0_snoc_periph_clk, - [RPM_SMD_SNOC_PERIPH_A_CLK] = &clk_smd_rpm_bus_0_snoc_periph_a_clk, - [RPM_SMD_SNOC_LPASS_CLK] = &clk_smd_rpm_bus_5_snoc_lpass_clk, - [RPM_SMD_SNOC_LPASS_A_CLK] = &clk_smd_rpm_bus_5_snoc_lpass_a_clk, - [RPM_SMD_CE1_CLK] = &clk_smd_rpm_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &clk_smd_rpm_ce1_a_clk, - [RPM_SMD_QPIC_CLK] = &clk_smd_rpm_qpic_clk, - [RPM_SMD_QPIC_CLK_A] = &clk_smd_rpm_qpic_a_clk, - [RPM_SMD_HWKM_CLK] = &clk_smd_rpm_hwkm_clk, - [RPM_SMD_HWKM_A_CLK] = &clk_smd_rpm_hwkm_a_clk, - [RPM_SMD_PKA_CLK] = &clk_smd_rpm_pka_clk, - [RPM_SMD_PKA_A_CLK] = &clk_smd_rpm_pka_a_clk, - [RPM_SMD_BIMC_GPU_CLK] = &clk_smd_rpm_bimc_gpu_clk, - [RPM_SMD_BIMC_GPU_A_CLK] = &clk_smd_rpm_bimc_gpu_a_clk, -}; - -static const struct rpm_smd_clk_desc rpm_clk_shikra = { - .clks = shikra_clks, - .num_clks = ARRAY_SIZE(shikra_clks), - .icc_clks = qcm2290_icc_clks, - .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) -}; - static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-mdm9607", .data = &rpm_clk_mdm9607 }, { .compatible = "qcom,rpmcc-msm8226", .data = &rpm_clk_msm8974 }, @@ -1347,7 +1314,6 @@ static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, { .compatible = "qcom,rpmcc-sdm429", .data = &rpm_clk_sdm429 }, { .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 }, - { .compatible = "qcom,rpmcc-shikra", .data = &rpm_clk_shikra }, { .compatible = "qcom,rpmcc-sm6115", .data = &rpm_clk_sm6115 }, { .compatible = "qcom,rpmcc-sm6125", .data = &rpm_clk_sm6125 }, { .compatible = "qcom,rpmcc-sm6375", .data = &rpm_clk_sm6375 }, From b12ca85e95d0585f126fcb829641a1e80e24dd9a Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:14 +0530 Subject: [PATCH 1027/1058] power: reset: reboot-mode: Remove devres based allocations Devres APIs are intended for use in drivers, and they should be avoided in shared subsystem code which is being used by multiple drivers. Avoid using devres based allocations in the reboot-mode subsystem and manually free the resources. Replace devm_kzalloc with kzalloc and handle memory cleanup explicitly. Fixes: 4fcd504edbf7 ("power: reset: add reboot mode driver") Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-1-46e085bca4cc@oss.qualcomm.com Signed-off-by: Anurag Pateriya Upstream-Status: Submitted [https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-1-46e085bca4cc@oss.qualcomm.com] --- drivers/power/reset/reboot-mode.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index d20e44db05325..1226eb49bc62d 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -3,6 +3,8 @@ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd */ +#define pr_fmt(fmt) "reboot-mode: " fmt + #include #include #include @@ -180,16 +182,15 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) if (strncmp(prop->name, PREFIX, len)) continue; - info = devm_kzalloc(reboot->dev, sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto error; } if (of_property_read_u32(np, prop->name, &info->magic)) { - dev_err(reboot->dev, "reboot mode %s without magic number\n", - info->mode); - devm_kfree(reboot->dev, info); + pr_err("reboot mode %s without magic number\n", info->mode); + kfree(info); continue; } @@ -200,8 +201,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) } else if (info->mode[0] == '\0') { kfree_const(info->mode); ret = -EINVAL; - dev_err(reboot->dev, "invalid mode name(%s): too short!\n", - prop->name); + pr_err("invalid mode name(%s): too short!\n", prop->name); goto error; } @@ -218,6 +218,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) return 0; error: + kfree(info); reboot_mode_unregister(reboot); return ret; } @@ -261,12 +262,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo int reboot_mode_unregister(struct reboot_mode_driver *reboot) { struct mode_info *info; + struct mode_info *next; unregister_reboot_notifier(&reboot->reboot_notifier); reboot_mode_unregister_device(reboot); - list_for_each_entry(info, &reboot->head, list) + list_for_each_entry_safe(info, next, &reboot->head, list) { + list_del(&info->list); kfree_const(info->mode); + kfree(info); + } return 0; } From 3bc2515f372ad4f7823e56356fe5ef6191d3b9c2 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:15 +0530 Subject: [PATCH 1028/1058] power: reset: reboot-mode: Add firmware node based registration The reboot-mode driver does not have a strict requirement for device-based registration. It primarily uses the device's of_node to read mode- properties. Remove the dependency on struct device and introduce support for firmware node (fwnode) based registration. This enables drivers that are not associated with a struct device to leverage the reboot-mode framework. Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-2-46e085bca4cc@oss.qualcomm.com Signed-off-by: Anurag Pateriya Upstream-Status: Submitted [https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-2-46e085bca4cc@oss.qualcomm.com] --- drivers/power/reset/reboot-mode.c | 17 ++++++++++++++--- include/linux/reboot-mode.h | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 1226eb49bc62d..e60b51987c254 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -165,17 +165,25 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) /** * reboot_mode_register - register a reboot mode driver * @reboot: reboot mode driver + * @fwnode: Firmware node with reboot-mode configuration * * Returns: 0 on success or a negative error code on failure. */ -int reboot_mode_register(struct reboot_mode_driver *reboot) +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode) { struct mode_info *info; + struct device_node *np; struct property *prop; - struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); int ret; + if (!fwnode) + return -EINVAL; + + np = to_of_node(fwnode); + if (!np) + return -EINVAL; + INIT_LIST_HEAD(&reboot->head); for_each_property_of_node(np, prop) { @@ -295,11 +303,14 @@ int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver **dr; int rc; + if (!reboot->dev || !reboot->dev->of_node) + return -EINVAL; + dr = devres_alloc(devm_reboot_mode_release, sizeof(*dr), GFP_KERNEL); if (!dr) return -ENOMEM; - rc = reboot_mode_register(reboot); + rc = reboot_mode_register(reboot, of_fwnode_handle(reboot->dev->of_node)); if (rc) { devres_free(dr); return rc; diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 4a2abb38d1d61..22f707ade4ba9 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -2,6 +2,8 @@ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ +#include + struct reboot_mode_driver { struct device *dev; struct list_head head; @@ -9,7 +11,7 @@ struct reboot_mode_driver { struct notifier_block reboot_notifier; }; -int reboot_mode_register(struct reboot_mode_driver *reboot); +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode); int reboot_mode_unregister(struct reboot_mode_driver *reboot); int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver *reboot); From 6c0aaef75223e2bd5c463dfa27ce15758c1c38c8 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:16 +0530 Subject: [PATCH 1029/1058] power: reset: reboot-mode: Add support for 64 bit magic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current reboot-mode supports a single 32-bit argument for any supported mode. Some reboot-mode based drivers may require passing two independent 32-bit arguments during a reboot sequence, for uses-cases, where a mode requires an additional argument. Such drivers may not be able to use the reboot-mode driver. For example, ARM PSCI vendor-specific resets, need two arguments for its operation – reset_type and cookie, to complete the reset operation. If a driver wants to implement this firmware-based reset, it cannot use reboot-mode framework. Introduce 64-bit magic values in reboot-mode driver to accommodate dual 32-bit arguments when specified via device tree. In cases, where no second argument is passed from device tree, keep the upper 32-bit of magic un-changed(0) to maintain backward compatibility. Update the current drivers using reboot-mode for a 64-bit magic value. Reviewed-by: Umang Chheda Reviewed-by: Nirmesh Kumar Singh Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-3-46e085bca4cc@oss.qualcomm.com Signed-off-by: Anurag Pateriya Upstream-Status: Submitted [https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-3-46e085bca4cc@oss.qualcomm.com] --- drivers/power/reset/nvmem-reboot-mode.c | 11 ++++++++--- drivers/power/reset/qcom-pon.c | 11 ++++++++--- drivers/power/reset/reboot-mode.c | 19 +++++++++++++------ drivers/power/reset/syscon-reboot-mode.c | 11 ++++++++--- include/linux/reboot-mode.h | 3 ++- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index d260715fccf67..4479c874077c7 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -17,14 +17,19 @@ struct nvmem_reboot_mode { struct nvmem_cell *cell; }; -static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct nvmem_reboot_mode *nvmem_rbm; size_t buf_len; + u32 magic_32; void *buf; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len); @@ -35,7 +40,7 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, if (buf_len > sizeof(magic)) return -EINVAL; - ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + ret = nvmem_cell_write(nvmem_rbm->cell, &magic_32, sizeof(magic_32)); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index 7e108982a582e..d0ed9431a0231 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c @@ -27,17 +27,22 @@ struct qcom_pon { long reason_shift; }; -static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct qcom_pon *pon = container_of (reboot, struct qcom_pon, reboot_mode); + u32 magic_32; int ret; + if (magic > U32_MAX || (magic << pon->reason_shift) > U32_MAX) + return -EINVAL; + + magic_32 = magic << pon->reason_shift; + ret = regmap_update_bits(pon->regmap, pon->baseaddr + PON_SOFT_RB_SPARE, GENMASK(7, pon->reason_shift), - magic << pon->reason_shift); + magic_32); if (ret < 0) dev_err(pon->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index e60b51987c254..55bc2243c9931 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -21,7 +21,7 @@ struct mode_info { const char *mode; - u32 magic; + u64 magic; struct list_head list; }; @@ -73,8 +73,7 @@ static const struct class reboot_mode_class = { .dev_groups = reboot_mode_groups, }; -static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - const char *cmd) +static u64 get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; struct mode_info *info; @@ -106,7 +105,7 @@ static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; - unsigned int magic; + u64 magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd); @@ -175,6 +174,8 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle struct device_node *np; struct property *prop; size_t len = strlen(PREFIX); + u32 magic_arg1; + u32 magic_arg2; int ret; if (!fwnode) @@ -196,12 +197,18 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle goto error; } - if (of_property_read_u32(np, prop->name, &info->magic)) { - pr_err("reboot mode %s without magic number\n", info->mode); + if (of_property_read_u32(np, prop->name, &magic_arg1)) { + pr_err("reboot mode without magic number\n"); kfree(info); continue; } + if (of_property_read_u32_index(np, prop->name, 1, &magic_arg2)) + magic_arg2 = 0; + + info->magic = magic_arg2; + info->magic = (info->magic << 32) | magic_arg1; + info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM; diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index e0772c9f70f7a..3cbd000c51223 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c @@ -20,16 +20,21 @@ struct syscon_reboot_mode { u32 mask; }; -static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct syscon_reboot_mode *syscon_rbm; + u32 magic_32; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot); ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset, - syscon_rbm->mask, magic); + syscon_rbm->mask, magic_32); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 22f707ade4ba9..e0d3e8a54050a 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -3,11 +3,12 @@ #define __REBOOT_MODE_H__ #include +#include struct reboot_mode_driver { struct device *dev; struct list_head head; - int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); + int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; }; From 5165ca9a1d5cf389e85563c5b550df185c6ad3ab Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 4 Jun 2026 15:36:07 +0530 Subject: [PATCH 1030/1058] firmware: psci: Implement vendor-specific resets as reboot-mode Implement PSCI SYSTEM_RESET2 vendor-specific resets by registering with the reboot-mode framework. A late_initcall registers the PSCI node's reboot-mode child, a reboot-mode write callback sets reset_type/cookie for the subsequent notifier, and a panic notifier clears the vendor reset state to avoid stale values after a kernel panic. Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-7-46e085bca4cc@oss.qualcomm.com Signed-off-by: Anurag Pateriya Upstream-Status: Submitted [https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-7-46e085bca4cc@oss.qualcomm.com] --- drivers/firmware/psci/Kconfig | 2 + drivers/firmware/psci/psci.c | 91 ++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/psci/Kconfig b/drivers/firmware/psci/Kconfig index 97944168b5e66..93ff7b071a0c3 100644 --- a/drivers/firmware/psci/Kconfig +++ b/drivers/firmware/psci/Kconfig @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config ARM_PSCI_FW bool + select POWER_RESET + select REBOOT_MODE config ARM_PSCI_CHECKER bool "ARM PSCI checker" diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e73bae6cb23a3..82f99c7a410f9 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -8,15 +8,18 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -51,6 +54,24 @@ static int resident_cpu = -1; struct psci_operations psci_ops; static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE; +struct psci_vendor_sysreset2 { + u32 reset_type; + u32 cookie; + bool valid; +}; + +static struct psci_vendor_sysreset2 vendor_reset; + +static int psci_panic_event(struct notifier_block *nb, unsigned long v, void *p) +{ + vendor_reset.valid = false; + return NOTIFY_DONE; +} + +static struct notifier_block psci_panic_block = { + .notifier_call = psci_panic_event +}; + bool psci_tos_resident_on(int cpu) { return cpu == resident_cpu; @@ -309,7 +330,10 @@ static int get_set_conduit_method(const struct device_node *np) static int psci_sys_reset(struct notifier_block *nb, unsigned long action, void *data) { - if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && + if (vendor_reset.valid && psci_system_reset2_supported) { + invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), vendor_reset.reset_type, + vendor_reset.cookie, 0); + } else if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { /* * reset_type[31] = 0 (architectural) @@ -557,6 +581,71 @@ static const struct platform_suspend_ops psci_suspend_ops = { .begin = psci_system_suspend_begin, }; +static int psci_set_vendor_sys_reset2(struct reboot_mode_driver *reboot, u64 magic) +{ + u32 magic_32; + + if (psci_system_reset2_supported) { + magic_32 = magic & GENMASK(31, 0); + vendor_reset.reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic_32; + vendor_reset.cookie = (magic >> 32) & GENMASK(31, 0); + vendor_reset.valid = true; + } + + return NOTIFY_DONE; +} + +static int __init psci_init_vendor_reset(void) +{ + struct reboot_mode_driver *reboot; + struct device_node *psci_np; + struct device_node *np; + int ret; + + if (!psci_system_reset2_supported) + return -EINVAL; + + psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0"); + if (!psci_np) + return -ENODEV; + + np = of_find_node_by_name(psci_np, "reboot-mode"); + if (!np) { + of_node_put(psci_np); + return -ENODEV; + } + + ret = atomic_notifier_chain_register(&panic_notifier_list, &psci_panic_block); + if (ret) + goto err_notifier; + + reboot = kzalloc(sizeof(*reboot), GFP_KERNEL); + if (!reboot) { + ret = -ENOMEM; + goto err_kzalloc; + } + + reboot->write = psci_set_vendor_sys_reset2; + + ret = reboot_mode_register(reboot, of_fwnode_handle(np)); + if (ret) + goto err_register; + + of_node_put(psci_np); + of_node_put(np); + return 0; + +err_register: + kfree(reboot); +err_kzalloc: + atomic_notifier_chain_unregister(&panic_notifier_list, &psci_panic_block); +err_notifier: + of_node_put(psci_np); + of_node_put(np); + return ret; +} +late_initcall(psci_init_vendor_reset) + static void __init psci_init_system_reset2(void) { int ret; From f65ae3e5fa3c3696b6daa9d3c39df95afa8ed3bb Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 8 May 2026 09:36:34 +0530 Subject: [PATCH 1031/1058] WORKAROUND: power: reset: reboot-mode: fix NULL deref when dev is not set reboot_mode_create_device() and reboot_mode_unregister_device() unconditionally dereference reboot->dev->driver->name to name the sysfs device. psci_init_vendor_reset() allocates a reboot_mode_driver with kzalloc (so reboot->dev == NULL) and never sets reboot->dev, causing a NULL pointer dereference at boot: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000068 pc : reboot_mode_register+0x334/0x3b8 psci_init_vendor_reset+0xdc/0x128 Kernel panic - not syncing: Oops: Fatal exception The offset 0x68 is the 'driver' pointer inside struct device on arm64, confirming that reboot->dev itself is NULL. Fix this by adding a 'name' field to struct reboot_mode_driver. reboot_mode_create_device() and reboot_mode_unregister_device() now prefer reboot->name; they fall back to reboot->dev->driver->name only when reboot->name is NULL, and return -EINVAL / return early if neither source is available. Set reboot->name = "psci" in psci_init_vendor_reset() so the sysfs device is correctly named. Existing device-based callers (nvmem-reboot-mode, syscon-reboot-mode, qcom-pon) are unaffected: they set reboot->dev before calling devm_reboot_mode_register(), so the fallback path is taken as before. Fixes: cfaf0a90789a ("power: reset: reboot-mode: Expose sysfs for registered reboot_modes") Fixes: 614b17a3ce6e ("firmware: psci: Implement vendor-specific resets as reboot-mode") Reported-by: LAVA job 91409 Signed-off-by: Salendarsingh Gaud Signed-off-by: Anurag Pateriya Upstream-Status: Inappropriate [workaround] --- drivers/firmware/psci/psci.c | 1 + drivers/power/reset/reboot-mode.c | 20 ++++++++++++++++++-- include/linux/reboot-mode.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index 82f99c7a410f9..158a0a1b9b879 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -626,6 +626,7 @@ static int __init psci_init_vendor_reset(void) } reboot->write = psci_set_vendor_sys_reset2; + reboot->name = "psci"; ret = reboot_mode_register(reboot, of_fwnode_handle(np)); if (ret) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 55bc2243c9931..0b9179100335f 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -120,8 +120,16 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) struct reboot_mode_sysfs_data *priv; struct mode_info *sysfs_info; struct mode_info *info; + const char *dev_name; int ret; + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return -EINVAL; + dev_name = reboot->dev->driver->name; + } + priv = kzalloc_obj(*priv, GFP_KERNEL); if (!priv) return -ENOMEM; @@ -147,7 +155,7 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) priv->reboot_mode_device = device_create(&reboot_mode_class, NULL, 0, (void *)priv, "%s", - reboot->dev->driver->name); + dev_name); if (IS_ERR(priv->reboot_mode_device)) { ret = PTR_ERR(priv->reboot_mode_device); goto error; @@ -253,8 +261,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo { struct reboot_mode_sysfs_data *priv; struct device *reboot_mode_device; + const char *dev_name; + + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return; + dev_name = reboot->dev->driver->name; + } - reboot_mode_device = class_find_device(&reboot_mode_class, NULL, reboot->dev->driver->name, + reboot_mode_device = class_find_device(&reboot_mode_class, NULL, dev_name, reboot_mode_match_by_name); if (!reboot_mode_device) diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index e0d3e8a54050a..56581199af234 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -7,6 +7,7 @@ struct reboot_mode_driver { struct device *dev; + const char *name; struct list_head head; int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; From 7c3c83a180d44aca61d63879bc23d6c3a95c8330 Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Tue, 9 Jun 2026 22:43:48 +0530 Subject: [PATCH 1032/1058] ASoC: qcom: sc8280xp: add Shikra audio support Add Shikra-specific audio support to the sc8280xp machine driver. Register Shikra board DAPM widgets and pin controls for Headphone, Headset Mic, Int Mic and Speaker endpoints. Add per-board control data to struct snd_soc_common so board-specific controls can be registered with the card during probe. Add MI2S codec clock configuration through board flags instead of relying on the number of codecs in the DAI link. Shikra uses codec_dai_fmt and codec_sysclk_set to request codec DAI format and sysclk programming, while mi2s_bclk_enable controls CPU MCLK programming for boards that need it. Handle TDM setup from hw_params, where slot configuration and BCLK can be computed from stream parameters, rather than programming the TDM format from snd_init. Also add qcom,adsp-bypass-mode handling so boards using CPU-based audio can skip DSP-oriented hw_params programming. Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik Signed-off-by: Pratyush Meduri --- sound/soc/qcom/sc8280xp.c | 52 +++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 3ada558f9ffeb..5e98f8c428338 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -34,13 +34,32 @@ static const struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { SND_SOC_DAPM_SPK("DP7 Jack", NULL), }; +static const struct snd_soc_dapm_widget shikra_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new shikra_controls[] = { + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + struct snd_soc_common { const char *driver_name; const struct snd_soc_dapm_widget *dapm_widgets; int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; int num_dapm_routes; + const struct snd_kcontrol_new *controls; + int num_controls; bool mi2s_mclk_enable; + bool mi2s_bclk_enable; + unsigned int codec_dai_fmt; + bool codec_sysclk_set; }; struct sc8280xp_snd_data { @@ -49,6 +68,7 @@ struct sc8280xp_snd_data { struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; const struct snd_soc_common *snd_soc_common_priv; + bool dsp_bypass_mode; bool jack_setup; }; @@ -122,8 +142,6 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) int dp_pcm_id = 0; switch (cpu_dai->id) { - case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: - return sc8280xp_tdm_set_dai_fmt(rtd, cpu_dai); case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: /* @@ -220,6 +238,10 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); unsigned int mclk_freq = sc8280xp_get_mclk_feq(params_rate(params)); int ret; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + + if (data->dsp_bypass_mode) + return 0; switch (cpu_dai->id) { case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: @@ -228,7 +250,15 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, if (ret < 0 && ret != -EOPNOTSUPP) return ret; - if (!data->snd_soc_common_priv->mi2s_mclk_enable) + if (data->snd_soc_common_priv->codec_dai_fmt) + snd_soc_dai_set_fmt(codec_dai, + data->snd_soc_common_priv->codec_dai_fmt); + + if (data->snd_soc_common_priv->codec_sysclk_set) + snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, + SND_SOC_CLOCK_IN); + + if (!data->snd_soc_common_priv->mi2s_bclk_enable) return 0; ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_MCLK, @@ -301,11 +331,16 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) card->num_dapm_widgets = data->snd_soc_common_priv->num_dapm_widgets; card->dapm_routes = data->snd_soc_common_priv->dapm_routes; card->num_dapm_routes = data->snd_soc_common_priv->num_dapm_routes; + card->controls = data->snd_soc_common_priv->controls; + card->num_controls = data->snd_soc_common_priv->num_controls; ret = qcom_snd_parse_of(card); if (ret) return ret; + data->dsp_bypass_mode = of_property_read_bool(dev->of_node, + "qcom,adsp-bypass-mode"); + card->driver_name = data->snd_soc_common_priv->driver_name; sc8280xp_add_be_ops(card); return devm_snd_soc_register_card(dev, card); @@ -356,8 +391,15 @@ static const struct snd_soc_common sc8280xp_priv_data = { static const struct snd_soc_common shikra_priv_data = { .driver_name = "shikra", - .dapm_widgets = sc8280xp_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), + .dapm_widgets = shikra_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_dapm_widgets), + .controls = shikra_controls, + .num_controls = ARRAY_SIZE(shikra_controls), + .mi2s_bclk_enable = true, + .codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S, + .codec_sysclk_set = true, }; static const struct snd_soc_common sm8450_priv_data = { From 0778019458f01b14c21263b756242cff4844e2be Mon Sep 17 00:00:00 2001 From: Raviteja Laggyshetty Date: Tue, 26 May 2026 17:21:02 +0000 Subject: [PATCH 1033/1058] interconnect: qcom: Enable Shikra interconnect driver by default for ARCH_QCOM Interconnect drivers provide fundamental NoC bandwidth management required for correct system behavior. Although systems can boot without them, power and performance are impacted. These drivers need to enabled irresepective of the board variant, design or configuration. Enable the Shikra interconnect driver by default on ARCH_QCOM by setting "default ARCH_QCOM". Signed-off-by: Raviteja Laggyshetty Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260526-shikra_icc_kconfig-v1-1-c589db2d023c@oss.qualcomm.com --- drivers/interconnect/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 5b8a094ca4ede..baec7eb4c24be 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -333,6 +333,7 @@ config INTERCONNECT_QCOM_SHIKRA tristate "Qualcomm SHIKRA interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + default ARCH_QCOM select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on shikra-based From f24f5358b426454c32f6f401669b20295c853536 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:06:57 +0530 Subject: [PATCH 1034/1058] FROMLIST: dt-bindings: net: qcom,ethqos: add qcom,shikra-ethqos compatible Shikra's EMAC requires three additional clocks beyond the standard four (axi, axi-noc, pcie-tile-axi-noc) for NOC interconnect voting. Add the compatible string and extend clock-names with a oneOf variant for this seven-clock configuration. The AXI clock appears twice (as "stmmaceth" and "axi") because the stmmac core and the driver's NOC bulk-clock array each consume one reference; CCF refcounting makes this safe. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../devicetree/bindings/net/qcom,ethqos.yaml | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml index 423959cb928d9..4528946856c8c 100644 --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml @@ -32,6 +32,7 @@ properties: - qcom,qcs404-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos + - qcom,shikra-ethqos - qcom,sm8150-ethqos reg: @@ -57,16 +58,30 @@ properties: - const: sfty clocks: - maxItems: 4 + minItems: 4 + maxItems: 7 clock-names: - items: - - const: stmmaceth - - const: pclk - - const: ptp_ref - - enum: - - rgmii - - phyaux + oneOf: + - items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - enum: + - rgmii + - phyaux + - description: | + Extended clock list for platforms with AXI NOC clocks that require + explicit driver management (e.g. Shikra). GCC_EMAC0_AXI_CLK appears + as both "stmmaceth" and "axi"; CCF refcounting makes this safe. + items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - const: rgmii + - const: axi + - const: axi-noc + - const: pcie-tile-axi-noc iommus: maxItems: 1 From 1bc7abd4c9fea977132cad13a2b67964378d1e13 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:06:58 +0530 Subject: [PATCH 1035/1058] FROMLIST: net: stmmac: qcom-ethqos: convert ethqos_rgmii_macro_init() to void The return value is never checked by its sole caller and the speed validation duplicates a check higher up the call stack. Convert to void and remove the dead code. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ac7d6d3e205a1..44270c25d874f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -371,9 +371,8 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) return 0; } -static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) +static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { - struct device *dev = ðqos->pdev->dev; unsigned int prg_rclk_dly, loopback; unsigned int phase_shift; @@ -384,11 +383,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); - if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) { - dev_err(dev, "Invalid speed %d\n", speed); - return -EINVAL; - } - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); if (speed == SPEED_1000) { @@ -479,8 +473,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, RGMII_IO_MACRO_CONFIG); - - return 0; } static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, From d756b68ff30d88ca62c5e82e49269c10644c4343 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:06:59 +0530 Subject: [PATCH 1036/1058] FROMLIST: net: stmmac: qcom-ethqos: fix RGMII_ID mode to use DLL bypass When "rgmii-id" is selected the PHY supplies both TX and RX delays, so the MAC must not add its own. The driver currently falls through to the generic DLL initialisation path which programs it to add a delay. Power down the DLL and set DDR bypass mode for RGMII_ID, then program the IO_MACRO via a new ethqos_rgmii_id_macro_init() helper. Also fix ethqos_set_clk_tx_rate() to not double the clock rate in bypass mode at 100M/10M, and remove RGMII_ID from the phase-shift suppression in ethqos_rgmii_macro_init() since RGMII_ID no longer reaches that path. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 44270c25d874f..bec08f1eb8cb4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -67,6 +67,9 @@ /* SDC4_STATUS bits */ #define SDC4_STATUS_DLL_LOCK BIT(7) +/* SDCC_USR_CTL bits */ +#define SDCC_USR_CTL_DDR_BYPASS BIT(30) + /* RGMII_IO_MACRO_CONFIG2 fields */ #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) @@ -183,7 +186,15 @@ static int ethqos_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, if (rate < 0) return rate; - return clk_set_rate(ethqos->link_clk, rate * 2); + /* Clock Rate Requirements: + * MAC added delay: 250/50/5 Mhz for 1G/100M/10M + * No MAC delay (DLL bypass): 250/25/2.5 Mhz for 1G/100M/10M + */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII || + speed == SPEED_1000) + rate *= 2; + + return clk_set_rate(ethqos->link_clk, rate); } static void @@ -405,8 +416,7 @@ static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG2); /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) phase_shift = 0; else phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; @@ -475,6 +485,40 @@ static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG); } +static void ethqos_rgmii_id_macro_init(struct qcom_ethqos *ethqos, int speed) +{ + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + else + rgmii_clrmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + + if (ethqos->has_emac_ge_3) + rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + + if (!ethqos->rgmii_config_loopback_en) + rgmii_clrmask(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + + rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); +} + static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, phy_interface_t interface, int speed, unsigned int mode) @@ -493,6 +537,21 @@ static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, ethqos_set_func_clk_en(ethqos); + /* For rgmii-id mode, the PHY should add the required delays. + * Therefore, power down the DLL and program it in bypass mode. + * Program the IO_MACRO as per the settings recommended by the + * programming guide for bypass mode. This will ensure that the + * MAC core doesn't add any additional delays. + */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID) { + rgmii_setmask(ethqos, SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + rgmii_setmask(ethqos, SDCC_USR_CTL_DDR_BYPASS, SDCC_USR_CTL); + + ethqos_rgmii_id_macro_init(ethqos, speed); + + return; + } + /* Initialize the DLL first */ /* Set DLL_RST */ From 358b63efc08ffa8180d597f63154029489fcb036 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:00 +0530 Subject: [PATCH 1037/1058] FROMLIST: net: stmmac: qcom-ethqos: add per-platform NOC clock voting Some SoCs gate the EMAC's path to the System NOC behind dedicated clocks that must be enabled before the DMA can reach memory. Add ethqos_noc_clk_cfg and the corresponding fields in the driver-data and runtime structs so each compatible can declare its own set with per-clock rates. The clocks are acquired during probe and enabled/disabled alongside the existing link clock in ethqos_clks_config(). No functional change for existing compatibles. This will help us when we add support for Shikra. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index bec08f1eb8cb4..f4d4b419a7627 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -84,11 +84,18 @@ #define SGMII_10M_RX_CLK_DVDR 0x31 +#define ETHQOS_MAX_NOC_CLKS 3 + struct ethqos_emac_por { unsigned int offset; unsigned int value; }; +struct ethqos_noc_clk_cfg { + const char *id; + unsigned long rate; +}; + struct ethqos_emac_driver_data { const struct ethqos_emac_por *rgmii_por; unsigned int num_rgmii_por; @@ -98,6 +105,8 @@ struct ethqos_emac_driver_data { const char *link_clk_name; struct dwmac4_addrs dwmac4_addrs; bool needs_sgmii_loopback; + const struct ethqos_noc_clk_cfg *noc_clk_cfg; + unsigned int num_noc_clks; }; struct qcom_ethqos { @@ -112,6 +121,9 @@ struct qcom_ethqos { bool rgmii_config_loopback_en; bool has_emac_ge_3; bool needs_sgmii_loopback; + + struct clk_bulk_data noc_clks[ETHQOS_MAX_NOC_CLKS]; + int num_noc_clks; }; static u32 rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) @@ -696,6 +708,17 @@ static int ethqos_clks_config(void *priv, bool enabled) return ret; } + if (ethqos->num_noc_clks) { + ret = clk_bulk_prepare_enable(ethqos->num_noc_clks, + ethqos->noc_clks); + if (ret) { + dev_err(ðqos->pdev->dev, + "NOC clocks enable failed: %d\n", ret); + clk_disable_unprepare(ethqos->link_clk); + return ret; + } + } + /* Enable functional clock to prevent DMA reset to timeout due * to lacking PHY clock after the hardware block has been power * cycled. The actual configuration will be adjusted once @@ -704,6 +727,9 @@ static int ethqos_clks_config(void *priv, bool enabled) qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); } else { + if (ethqos->num_noc_clks) + clk_bulk_disable_unprepare(ethqos->num_noc_clks, + ethqos->noc_clks); clk_disable_unprepare(ethqos->link_clk); } @@ -732,6 +758,37 @@ static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv) netdev_dbg(priv->dev, "PTP rate %lu\n", plat_dat->clk_ptp_rate); } +/* + * Some SoCs gate interconnect access to the System NOC behind dedicated + * clocks. Acquire them, set their required rates, and store the result in + * ethqos so ethqos_clks_config() can enable/disable them at runtime. + */ +static int qcom_ethqos_init_noc_clks(struct qcom_ethqos *ethqos, + const struct ethqos_emac_driver_data *data) +{ + struct device *dev = ðqos->pdev->dev; + unsigned int i; + int ret; + + for (i = 0; i < data->num_noc_clks; i++) + ethqos->noc_clks[i].id = data->noc_clk_cfg[i].id; + ethqos->num_noc_clks = data->num_noc_clks; + + ret = devm_clk_bulk_get(dev, ethqos->num_noc_clks, ethqos->noc_clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get NOC clocks\n"); + + for (i = 0; i < data->num_noc_clks; i++) { + ret = clk_set_rate(ethqos->noc_clks[i].clk, + data->noc_clk_cfg[i].rate); + if (ret) + dev_warn(dev, "Failed to set %s rate: %d\n", + data->noc_clk_cfg[i].id, ret); + } + + return 0; +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -791,6 +848,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->has_emac_ge_3 = data->has_emac_ge_3; ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback; + if (data->num_noc_clks) { + ret = qcom_ethqos_init_noc_clks(ethqos, data); + if (ret) + return ret; + } + ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); if (IS_ERR(ethqos->link_clk)) return dev_err_probe(dev, PTR_ERR(ethqos->link_clk), From c5e75e20d241325b547bb867b42539eafa0d02ee Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Fri, 12 Jun 2026 00:07:01 +0530 Subject: [PATCH 1038/1058] FROMLIST: net: stmmac: qcom-ethqos: add Shikra EMAC support Shikra integrates two Qualcomm ETHQOS controllers based on the Synopsys GMAC IP, similar to previous platforms. Register qcom,shikra-ethqos backed by a new shikra_data descriptor that enables the three NOC clocks required for DMA memory access and the 36-bit DMA address width. Link: https://lore.kernel.org/netdev/20260612-shikra_ethernet-v1-0-f0f4a1d19929@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index f4d4b419a7627..59fa8779e4e46 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -326,6 +326,36 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { }, }; +static const struct ethqos_noc_clk_cfg shikra_noc_clks[] = { + { "axi", 120000000 }, + { "axi-noc", 120000000 }, + { "pcie-tile-axi-noc", 120000000 }, +}; + +static const struct ethqos_emac_driver_data shikra_data = { + .dma_addr_width = 36, + .has_emac_ge_3 = true, + .noc_clk_cfg = shikra_noc_clks, + .num_noc_clks = ARRAY_SIZE(shikra_noc_clks), + .rgmii_config_loopback_en = false, + .dwmac4_addrs = { + .dma_chan = 0x00008100, + .dma_chan_offset = 0x1000, + .mtl_chan = 0x00008000, + .mtl_chan_offset = 0x1000, + .mtl_ets_ctrl = 0x00008010, + .mtl_ets_ctrl_offset = 0x1000, + .mtl_txq_weight = 0x00008018, + .mtl_txq_weight_offset = 0x1000, + .mtl_send_slp_cred = 0x0000801c, + .mtl_send_slp_cred_offset = 0x1000, + .mtl_high_cred = 0x00008020, + .mtl_high_cred_offset = 0x1000, + .mtl_low_cred = 0x00008024, + .mtl_low_cred_offset = 0x1000, + }, +}; + static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { struct device *dev = ðqos->pdev->dev; @@ -915,6 +945,7 @@ static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data}, { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data}, + { .compatible = "qcom,shikra-ethqos", .data = &shikra_data}, { .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data}, { } }; From cd0a8828d5f9bb73a5e24db72b65e5ef9bb902cb Mon Sep 17 00:00:00 2001 From: Faiyaz Mohammed Date: Wed, 17 Jun 2026 19:11:34 +0530 Subject: [PATCH 1039/1058] soc: qcom: llcc: Skip ECC interrupt setup on Shikra, pre-configured by DSF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Shikra, the DDR System Firmware (DSF) configures ECC interrupt routing before the kernel driver probes — it enables Tag/Data RAM interrupts and programs error thresholds in the LLCC interrupt-enable registers. Set irq_configured in shikra_cfg so that qcom_llcc_edac_probe() skips calling qcom_llcc_core_setup(), which would otherwise overwrite the firmware-managed register state with redundant writes. Signed-off-by: Faiyaz Mohammed --- drivers/soc/qcom/llcc-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 22c8099cf6bbb..733999867bbf6 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4595,6 +4595,7 @@ static const struct qcom_llcc_config shikra_cfg[] = { .size = ARRAY_SIZE(shikra_data), .reg_offset = llcc_v2_1_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .irq_configured = true, }, }; From 7d11ff3e3085b80cf8a941eeac9e75aa6565fdc6 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 11 Jun 2026 14:42:58 +0530 Subject: [PATCH 1040/1058] clk: qcom: gcc-shikra: Add additional frequencies for EMAC RGMII clocks Add support for additional GCC EMAC RGMII clock frequencies (2.5MHz and 25MHz) required for the EMAC use-cases on Qualcomm Shikra SoC. While at it, correct the GPLL8/9/10 test_ctl_hi_val configuration. Signed-off-by: Imran Shaik --- drivers/clk/qcom/gcc-shikra.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/gcc-shikra.c b/drivers/clk/qcom/gcc-shikra.c index 65cd42e0334de..e7b692d7d3496 100644 --- a/drivers/clk/qcom/gcc-shikra.c +++ b/drivers/clk/qcom/gcc-shikra.c @@ -123,7 +123,7 @@ static const struct alpha_pll_config gpll10_config = { .vco_mask = GENMASK(21, 20), .main_output_mask = BIT(0), .config_ctl_val = 0x4001055b, - .test_ctl_hi1_val = 0x1, + .test_ctl_hi_val = 0x1, }; static struct clk_alpha_pll gpll10 = { @@ -156,7 +156,7 @@ static const struct alpha_pll_config gpll11_config = { .vco_mask = GENMASK(21, 20), .main_output_mask = BIT(0), .config_ctl_val = 0x4001055b, - .test_ctl_hi1_val = 0x1, + .test_ctl_hi_val = 0x1, }; static struct clk_alpha_pll gpll11 = { @@ -361,7 +361,7 @@ static const struct alpha_pll_config gpll8_config = { .post_div_val = BIT(8), .post_div_mask = GENMASK(11, 8), .config_ctl_val = 0x4001055b, - .test_ctl_hi1_val = 0x1, + .test_ctl_hi_val = 0x1, }; static struct clk_alpha_pll gpll8 = { @@ -1244,6 +1244,8 @@ static struct clk_rcg2 gcc_emac0_ptp_clk_src = { }; static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = { + F(2500000, P_GPLL0_OUT_AUX2, 10, 1, 12), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), F(125000000, P_GPLL12_OUT_AUX2, 4, 0, 0), F(250000000, P_GPLL12_OUT_EARLY, 4, 0, 0), From 099ae4c118f8f459de596f8a82b0128981e5e9bf Mon Sep 17 00:00:00 2001 From: Pratyush Meduri Date: Wed, 17 Jun 2026 22:42:06 +0530 Subject: [PATCH 1041/1058] ASoC: qcom: q6apm: Propagate shared memory unmap status Use the result payload returned for APM_CMD_SHARED_MEM_UNMAP_REGIONS instead of forcing a successful completion. Clear the memory map handle only when the DSP reports success, and keep error reporting tied to the returned status so callers can detect failed unmap operations. Signed-off-by: Pratyush Meduri --- sound/soc/qcom/qdsp6/q6apm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index a65d6793353a4..99d0f30e31a34 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -965,14 +965,13 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op) wake_up(&apm->wait); break; case APM_CMD_SHARED_MEM_UNMAP_REGIONS: - apm->result.opcode = hdr->opcode; - apm->result.status = 0; - rsp = data->payload; + apm->result.opcode = result->opcode; + apm->result.status = result->status; info = idr_find(&apm->graph_info_idr, hdr->token); - if (info) + if (info && !result->status) info->mem_map_handle = 0; - else + else if (!info || result->status) dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status, result->opcode); From c786c0bb3e3559b18e3fecf375eb4a32dfcf839e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Fri, 3 Jul 2026 13:45:13 +0530 Subject: [PATCH 1042/1058] ASoC: qcom: q6apm-dai: Support reserved memory buffers Add support for q6apm DAI instances that allocate PCM buffers from a reserved memory carveout instead of an IOMMU-mapped DMA allocation. Parse the optional memory-region property, size the ALSA buffer constraints to the carveout, and map the fixed physical region to the DSP graph when the stream is prepared. Support TrustZone VMID reassignment for both normal DMA buffers and reserved memory. Allow platforms to specify the source VMID tracked by SCM, share the buffer with the configured destination VMIDs, and restore ownership during stream teardown. Signed-off-by: Pratyush Meduri --- sound/soc/qcom/qdsp6/q6apm-dai.c | 638 +++++++++++++++++++++++++++---- 1 file changed, 570 insertions(+), 68 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index cccb6444ddf5c..ed4c2013dc3bf 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -1,21 +1,23 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2021, Linaro 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 "q6apm.h" #define DRV_NAME "q6apm-dai" @@ -36,7 +38,10 @@ #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) #define Q6APM_MAX_VMIDS 8 -#define Q6APM_SCM_MAX_VMID 31 +#define Q6APM_RESERVED_BUFFER_BYTES_MAX (256 * 1024) +#define Q6APM_SCM_MAX_VMID QCOM_SCM_VMID_ADSP_HEAP +#define Q6APM_STATIC_AUDIO_CARVEOUT_ADDR 0x86200000ULL +#define Q6APM_STATIC_AUDIO_CARVEOUT_SIZE 0x40000 #define SID_MASK_DEFAULT 0xF static const struct snd_compr_codec_caps q6apm_compr_caps = { @@ -76,7 +81,7 @@ struct q6apm_dai_rtd { unsigned int push_pull_size; unsigned int pcm_count; unsigned int periods; - unsigned int scm_size; + size_t scm_size; uint64_t bytes_sent; uint64_t bytes_received; uint64_t copied_total; @@ -84,6 +89,7 @@ struct q6apm_dai_rtd { snd_pcm_uframes_t queue_ptr; bool next_track; bool scm_assigned; + bool memory_mapped; u64 scm_src_perms; enum stream_state state; struct q6apm_graph *graph; @@ -92,26 +98,48 @@ struct q6apm_dai_rtd { }; struct q6apm_dai_data { + struct device *dev; long long sid; int num_vmids; u32 vmids[Q6APM_MAX_VMIDS]; + u32 src_vmid; bool use_scm_assign; + bool use_reserved_mem; + bool reserved_mem_assigned; + phys_addr_t reserved_mem_addr; + size_t reserved_mem_size; + bool aux_mem_assigned; + phys_addr_t aux_mem_addr; + size_t aux_mem_size; + size_t buffer_bytes_max; + u64 reserved_mem_src_perms; + u64 aux_mem_src_perms; }; static int q6apm_dai_assign_memory(struct q6apm_dai_rtd *prtd, const struct q6apm_dai_data *pdata) { struct qcom_scm_vmperm *dst_vmids; + phys_addr_t aligned_addr; + size_t aligned_size; + phys_addr_t addr; + size_t offset; int dst_count = 0; int ret; int i; + struct device *dev = prtd->substream->pcm->card->dev; - if (!pdata->use_scm_assign || pdata->num_vmids <= 0 || prtd->scm_assigned) + if (!pdata->use_scm_assign || pdata->use_reserved_mem || + pdata->num_vmids <= 0 || prtd->scm_assigned) return 0; /* hw_params() validates and sets dma_addr_valid before prepare(). */ - if (!prtd->dma_addr_valid || !prtd->pcm_size) + if (!prtd->dma_addr_valid || !prtd->pcm_size) { + dev_err(dev, + "SCM assign: buffer not ready (dma_addr_valid=%d pcm_size=%u)\n", + prtd->dma_addr_valid, prtd->pcm_size); return -EINVAL; + } dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); if (!dst_vmids) @@ -123,11 +151,8 @@ static int q6apm_dai_assign_memory(struct q6apm_dai_rtd *prtd, dst_count++; for (i = 0; i < pdata->num_vmids; i++) { - /* - * Probe-time validation rejects HLOS in qcom,vmid, so this is - * only a defensive check for future non-DT vmids[] population. - */ - if (WARN_ON_ONCE(pdata->vmids[i] == QCOM_SCM_VMID_HLOS)) + /* HLOS is already added above; skip it if listed in qcom,vmid. */ + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) continue; dst_vmids[dst_count].vmid = pdata->vmids[i]; @@ -141,15 +166,34 @@ static int q6apm_dai_assign_memory(struct q6apm_dai_rtd *prtd, return 0; } - prtd->scm_size = ALIGN(prtd->pcm_size, PAGE_SIZE); - prtd->scm_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + addr = prtd->dma_addr; + aligned_addr = ALIGN_DOWN(addr, PAGE_SIZE); + offset = addr - aligned_addr; + aligned_size = PAGE_ALIGN(prtd->pcm_size + offset); + + prtd->scm_size = aligned_size; + prtd->scm_src_perms = BIT_ULL(pdata->src_vmid); - ret = qcom_scm_assign_mem(prtd->dma_addr, prtd->scm_size, + dev_dbg(dev, + "SCM assign: addr=%pa size=%zu src_vmid=0x%x dst_count=%d\n", + &aligned_addr, prtd->scm_size, pdata->src_vmid, dst_count); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM assign: dst[%d] vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(aligned_addr, prtd->scm_size, &prtd->scm_src_perms, dst_vmids, dst_count); kfree(dst_vmids); - if (ret) + if (ret) { + dev_err(dev, + "SCM assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &aligned_addr, prtd->scm_size, pdata->src_vmid, ret); return ret; + } + dev_dbg(dev, + "SCM assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &aligned_addr, prtd->scm_size, prtd->scm_src_perms); prtd->scm_assigned = true; return 0; } @@ -162,24 +206,254 @@ static int q6apm_dai_unassign_memory(struct q6apm_dai_rtd *prtd, .perm = QCOM_SCM_PERM_RW, }; struct device *dev = prtd->substream->pcm->card->dev; + phys_addr_t aligned_addr; + size_t aligned_size; + phys_addr_t addr; + size_t offset; int ret; if (!pdata->use_scm_assign || !prtd->scm_assigned) return 0; - ret = qcom_scm_assign_mem(prtd->dma_addr, prtd->scm_size, + addr = prtd->dma_addr; + aligned_addr = ALIGN_DOWN(addr, PAGE_SIZE); + offset = addr - aligned_addr; + aligned_size = PAGE_ALIGN(prtd->pcm_size + offset); + + dev_dbg(dev, + "SCM unassign: addr=%pa size=%zu src_perms=0x%llx\n", + &aligned_addr, aligned_size, prtd->scm_src_perms); + + ret = qcom_scm_assign_mem(aligned_addr, aligned_size, &prtd->scm_src_perms, &hlos, 1); if (!ret) { prtd->scm_assigned = false; prtd->scm_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM unassign ok: addr=%pa\n", &aligned_addr); } else { dev_err(dev, "Failed to unassign DMA buffer %pa from VMIDs: %d\n", &prtd->dma_addr, ret); + dev_err(dev, + "SCM unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &aligned_addr, aligned_size, prtd->scm_src_perms, ret); + } + + return ret; +} + +static int q6apm_dai_assign_reserved_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + struct device *dev = pdata->dev; + int dst_count = 0; + int ret; + int i; + + if (!pdata->use_reserved_mem || !pdata->use_scm_assign || + pdata->reserved_mem_assigned) + return 0; + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + if (dst_count == 1) { + kfree(dst_vmids); + return 0; } + pdata->reserved_mem_src_perms = BIT_ULL(pdata->src_vmid); + + dev_dbg(dev, + "SCM reserved assign begin: addr=%pa size=%zu src_vmid=0x%x dst_count=%d already_assigned=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->src_vmid, dst_count, pdata->reserved_mem_assigned); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM reserved assign dst[%d]: vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(pdata->reserved_mem_addr, + pdata->reserved_mem_size, + &pdata->reserved_mem_src_perms, + dst_vmids, dst_count); + if (ret) { + dev_err(dev, + "SCM reserved assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->src_vmid, ret); + } else { + pdata->reserved_mem_assigned = true; + dev_dbg(dev, + "SCM reserved assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms); + } + + kfree(dst_vmids); return ret; } +static int q6apm_dai_assign_aux_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + struct device *dev = pdata->dev; + int dst_count = 0; + int ret; + int i; + + if (!pdata->use_scm_assign || pdata->aux_mem_assigned || + !pdata->aux_mem_addr || !pdata->aux_mem_size) + return 0; + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + if (dst_count == 1) { + kfree(dst_vmids); + return 0; + } + + pdata->aux_mem_src_perms = BIT_ULL(pdata->src_vmid); + + dev_dbg(dev, + "SCM aux assign begin: addr=%pa size=%zu src_vmid=0x%x dst_count=%d already_assigned=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->src_vmid, dst_count, pdata->aux_mem_assigned); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM aux assign dst[%d]: vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(pdata->aux_mem_addr, pdata->aux_mem_size, + &pdata->aux_mem_src_perms, dst_vmids, dst_count); + if (ret) { + dev_err(dev, + "SCM aux assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->src_vmid, ret); + } else { + pdata->aux_mem_assigned = true; + dev_dbg(dev, + "SCM aux assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms); + } + + kfree(dst_vmids); + return ret; +} + +static int q6apm_dai_unassign_reserved_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = pdata->dev; + int ret; + + if (!pdata->use_reserved_mem || !pdata->reserved_mem_assigned) { + dev_dbg(dev, + "SCM reserved unassign skipped: use_reserved=%d assigned=%d\n", + pdata->use_reserved_mem, pdata->reserved_mem_assigned); + return 0; + } + + dev_dbg(dev, + "SCM reserved unassign begin: addr=%pa size=%zu src_perms=0x%llx\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms); + + ret = qcom_scm_assign_mem(pdata->reserved_mem_addr, + pdata->reserved_mem_size, + &pdata->reserved_mem_src_perms, &hlos, 1); + if (ret) { + dev_err(dev, + "SCM reserved unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms, ret); + return ret; + } + + pdata->reserved_mem_assigned = false; + pdata->reserved_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM reserved unassign ok: addr=%pa\n", + &pdata->reserved_mem_addr); + + return 0; +} + +static int q6apm_dai_unassign_aux_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = pdata->dev; + int ret; + + if (!pdata->aux_mem_assigned) { + dev_dbg(dev, "SCM aux unassign skipped: assigned=%d\n", + pdata->aux_mem_assigned); + return 0; + } + + dev_dbg(dev, + "SCM aux unassign begin: addr=%pa size=%zu src_perms=0x%llx\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms); + + ret = qcom_scm_assign_mem(pdata->aux_mem_addr, pdata->aux_mem_size, + &pdata->aux_mem_src_perms, &hlos, 1); + if (ret) { + dev_err(dev, + "SCM aux unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms, ret); + return ret; + } + + pdata->aux_mem_assigned = false; + pdata->aux_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM aux unassign ok: addr=%pa\n", + &pdata->aux_mem_addr); + + return 0; +} + +static void q6apm_dai_release_reserved_memory(void *data) +{ + struct q6apm_dai_data *pdata = data; + + q6apm_dai_unassign_aux_memory(pdata); + q6apm_dai_unassign_reserved_memory(pdata); + of_reserved_mem_device_release(pdata->dev); +} + static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | @@ -248,7 +522,7 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * } static void event_handler_compr(uint32_t opcode, uint32_t token, - void *payload, void *priv) + void *payload, void *priv) { struct q6apm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; @@ -304,13 +578,21 @@ static void event_handler_compr(uint32_t opcode, uint32_t token, } } +static int q6apm_dai_memory_unmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + +static int q6apm_dai_memory_map(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int graph_id, bool is_push_pull, size_t size); + static int q6apm_dai_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) + struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; struct audioreach_module_config cfg; struct device *dev = component->dev; + bool reserved_mapped_now = false; struct q6apm_dai_data *pdata; bool assigned_now = false; int ret; @@ -320,10 +602,49 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, return -EINVAL; if (!prtd || !prtd->graph) { - dev_err(dev, "%s: private data null or audio client freed\n", __func__); + dev_err(dev, "private data null or audio client freed\n"); return -EINVAL; } + if (pdata->use_reserved_mem && !prtd->memory_mapped) { + dev_dbg(dev, + "reserved prepare entry: assigned=%d mapped=%d dma=%pa phys=%pa pcm_size=%zu reserved=%pa/%zu graph=%d\n", + pdata->reserved_mem_assigned, prtd->memory_mapped, + &prtd->dma_addr, &prtd->phys, (size_t)prtd->pcm_size, + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + prtd->graph->id); + + ret = q6apm_dai_assign_aux_memory(pdata); + if (ret) { + dev_err(dev, "SCM aux assign failed at prepare: ret=%d\n", + ret); + return ret; + } + + if (!pdata->reserved_mem_assigned) { + ret = q6apm_dai_assign_reserved_memory(pdata); + if (ret) { + dev_err(dev, "SCM reserved assign failed at prepare: ret=%d\n", + ret); + return ret; + } + } + + dev_dbg(dev, + "reserved prepare: dma=%pa phys=%pa size=%zu graph=%d\n", + &prtd->dma_addr, &prtd->phys, (size_t)prtd->pcm_size, + prtd->graph->id); + + ret = q6apm_dai_memory_map(component, substream, + prtd->graph->id, false, prtd->pcm_size); + if (ret) + return ret; + prtd->memory_mapped = true; + reserved_mapped_now = true; + dev_dbg(dev, "reserved prepare map ok: graph=%d\n", + prtd->graph->id); + } + cfg.direction = substream->stream; cfg.sample_rate = runtime->rate; cfg.num_channels = runtime->channels; @@ -340,8 +661,11 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->pcm_count = snd_pcm_lib_period_bytes(substream); if (!prtd->scm_assigned) { ret = q6apm_dai_assign_memory(prtd, pdata); - if (ret) + if (ret) { + dev_err(dev, "SCM memory assign failed at prepare: ret=%d\n", + ret); return ret; + } assigned_now = prtd->scm_assigned; } @@ -371,7 +695,13 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, goto err_unassign; } } + dev_dbg(dev, "media_format_shmem success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, + "media_format_pcm begin: graph=%d dir=%u rate=%u channels=%u bit_width=%u\n", + prtd->graph->id, cfg.direction, cfg.sample_rate, + cfg.num_channels, cfg.bit_width); ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); if (ret < 0) { dev_err(dev, "%s: CMD Format block failed\n", __func__); @@ -384,16 +714,24 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, dev_err(dev, "Failed to set media format %d\n", ret); goto err_unassign; } + dev_dbg(dev, "alloc_fragments success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, "graph_prepare begin: graph=%d\n", + prtd->graph->id); ret = q6apm_graph_prepare(prtd->graph); if (ret) { - dev_err(dev, "Failed to prepare Graph %d\n", ret); + dev_err(dev, "q6apm_graph_prepare failed ret=%d\n", ret); goto err_unassign; } + dev_dbg(dev, "graph_prepare success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, "graph_start begin: graph=%d\n", + prtd->graph->id); ret = q6apm_graph_start(prtd->graph); if (ret) { - dev_err(dev, "Failed to Start Graph %d\n", ret); + dev_err(dev, "q6apm_graph_start failed ret=%d\n", ret); goto err_unassign; } if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) { @@ -413,6 +751,11 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, err_unassign: if (assigned_now) q6apm_dai_unassign_memory(prtd, pdata); + if (reserved_mapped_now) { + dev_err(dev, "reserved prepare error: unmapping graph after ret=%d\n", ret); + if (!q6apm_dai_memory_unmap(component, substream)) + prtd->memory_mapped = false; + } return ret; } @@ -431,7 +774,7 @@ static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub for (i = 0; i < avail_periods; i++) { ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); if (ret < 0) { - dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + dev_err(component->dev, "q6apm_write_async failed ret=%d\n", ret); return ret; } prtd->queue_ptr += runtime->period_size; @@ -485,7 +828,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - dev_err(dev, "Drv data not found ..\n"); + dev_err(dev, "Drv data not found\n"); return -EINVAL; } @@ -497,7 +840,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, prtd->substream = substream; prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id, substream->stream); if (IS_ERR(prtd->graph)) { - dev_err(dev, "%s: Could not allocate memory\n", __func__); + dev_err(dev, "q6apm_graph_open failed stream=%d\n", substream->stream); ret = PTR_ERR(prtd->graph); goto err; } @@ -506,19 +849,22 @@ static int q6apm_dai_open(struct snd_soc_component *component, runtime->hw = q6apm_dai_hardware_playback; else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) runtime->hw = q6apm_dai_hardware_capture; + runtime->hw.buffer_bytes_max = pdata->buffer_bytes_max; /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { - dev_err(dev, "snd_pcm_hw_constraint_integer failed\n"); + dev_err(dev, "snd_pcm_hw_constraint_integer failed ret=%d\n", ret); goto err; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - BUFFER_BYTES_MIN, BUFFER_BYTES_MAX); + BUFFER_BYTES_MIN, + pdata->buffer_bytes_max); if (ret < 0) { - dev_err(dev, "constraint for buffer bytes min max ret = %d\n", ret); + dev_err(dev, "buffer bytes minmax constraint failed ret=%d max=%zu\n", + ret, pdata->buffer_bytes_max); goto err; } } @@ -526,18 +872,18 @@ static int q6apm_dai_open(struct snd_soc_component *component, /* setup 10ms latency to accommodate DSP restrictions */ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { - dev_err(dev, "constraint for period bytes step ret = %d\n", ret); + dev_err(dev, "period size step constraint failed ret=%d\n", ret); goto err; } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { - dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); + dev_err(dev, "buffer size step constraint failed ret=%d\n", ret); goto err; } runtime->private_data = prtd; - runtime->dma_bytes = BUFFER_BYTES_MAX; + runtime->dma_bytes = pdata->buffer_bytes_max; prtd->scm_assigned = false; prtd->dma_addr_valid = false; prtd->dma_addr = substream->dma_buffer.addr; @@ -574,14 +920,25 @@ static int q6apm_dai_close(struct snd_soc_component *component, q6apm_graph_stop(prtd->graph); q6apm_free_fragments(prtd->graph, substream->stream); } + + if (prtd->memory_mapped) { + ret = q6apm_dai_memory_unmap(component, substream); + if (ret) + dev_err(component->dev, + "close(): memory unmap failed graph=%d ret=%d\n", + prtd->graph->id, ret); + else + prtd->memory_mapped = false; + } + if (pdata && prtd->scm_assigned) { ret = q6apm_dai_unassign_memory(prtd, pdata); if (ret) { - dev_warn(component->dev, - "close(): VMID unassign failed for DMA buffer %pa: %d\n", + dev_err(component->dev, + "close(): VMID unassign failed for DMA buffer %pa: %d\n", &prtd->dma_addr, ret); WARN_ONCE(1, "q6apm-dai: SCM VMID unassign leak for DMA buffer %pa\n", - &prtd->dma_addr); + &prtd->dma_addr); } } @@ -627,12 +984,15 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, } static int q6apm_dai_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai; struct q6apm_dai_rtd *prtd = runtime->private_data; struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); + dma_addr_t dma_addr; int ret; if (!pdata) @@ -641,18 +1001,23 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, if (prtd->scm_assigned) { ret = q6apm_dai_unassign_memory(prtd, pdata); if (ret) { - dev_warn(component->dev, - "hw_params(): failed to release previous VMID assignment: %d\n", + dev_err(component->dev, + "hw_params(): failed to release previous VMID assignment: %d\n", ret); return ret; } } - if (!substream->dma_buffer.addr) + dma_addr = runtime->dma_addr ? runtime->dma_addr : substream->dma_buffer.addr; + if (!dma_addr) return -ENOMEM; - prtd->dma_addr = substream->dma_buffer.addr; + prtd->dma_addr = dma_addr; prtd->dma_addr_valid = true; + if (pdata->sid < 0) + prtd->phys = dma_addr; + else + prtd->phys = dma_addr | (pdata->sid << 32); prtd->pcm_size = params_buffer_bytes(params); prtd->periods = params_periods(params); @@ -668,6 +1033,19 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, return -EINVAL; } + if (pdata->use_reserved_mem) { + if (!soc_prtd) + return -EINVAL; + + cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); + if (!cpu_dai) + return -EINVAL; + + dev_dbg(component->dev, + "reserved hw_params: dma=%pad size=%zu periods=%u\n", + &dma_addr, (size_t)prtd->pcm_size, prtd->periods); + } + return 0; } @@ -681,12 +1059,12 @@ static int q6apm_dai_hw_free(struct snd_soc_component *component, if (pdata && prtd->scm_assigned) { ret = q6apm_dai_unassign_memory(prtd, pdata); if (ret) - dev_warn(component->dev, - "hw_free(): VMID unassign failed for DMA buffer %pa: %d\n", + dev_err(component->dev, + "hw_free(): VMID unassign failed for DMA buffer %pa: %d\n", &prtd->dma_addr, ret); } - /* Fixed PCM DMA buffer is released in pcm_free(); close() retries unassign. */ + /* PCM DMA buffer is released by the ALSA managed buffer helpers. */ prtd->dma_addr_valid = false; return 0; @@ -694,27 +1072,47 @@ static int q6apm_dai_hw_free(struct snd_soc_component *component, static int q6apm_dai_memory_map(struct snd_soc_component *component, struct snd_pcm_substream *substream, - int graph_id, bool is_push_pull) + int graph_id, bool is_push_pull, size_t size) { struct q6apm_dai_data *pdata; struct device *dev = component->dev; + struct snd_pcm_runtime *runtime = substream->runtime; + dma_addr_t dma_addr; phys_addr_t phys; int ret; pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - dev_err(component->dev, "Drv data not found ..\n"); + dev_err(component->dev, "Drv data not found\n"); return -EINVAL; } - if (pdata->sid < 0) - phys = substream->dma_buffer.addr; - else - phys = substream->dma_buffer.addr | (pdata->sid << 32); + if (pdata->use_reserved_mem) { + phys = pdata->reserved_mem_addr; + size = pdata->reserved_mem_size; + dev_dbg(dev, "reserved map begin: phys=%pa size=%zu graph=%d\n", + &phys, size, graph_id); + } else { + if (runtime && runtime->dma_addr) + dma_addr = runtime->dma_addr; + else + dma_addr = substream->dma_buffer.addr; + if (!dma_addr) + return -ENOMEM; + + if (pdata->sid < 0) + phys = dma_addr; + else + phys = dma_addr | (pdata->sid << 32); + } - ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, BUFFER_BYTES_MAX); + ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, size); if (ret < 0) - dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); + dev_err(dev, "q6apm_map_memory_fixed_region failed rc=%d phys=%pa size=%zu graph=%d\n", + ret, &phys, size, graph_id); + else + dev_dbg(dev, "memory map done: phys=%pa size=%zu graph=%d\n", + &phys, size, graph_id); if (is_push_pull) { if (pdata->sid < 0) @@ -736,18 +1134,33 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc { struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_pcm *pcm = rtd->pcm; - /* - * Allocate one extra page as a workaround for a DSP bug where 32-bit - * address arithmetic can overflow when the buffer is placed near the - * end of the addressable range. - */ + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); int size = BUFFER_BYTES_MAX + PAGE_SIZE; int graph_id, ret; bool is_push_pull; struct snd_pcm_substream *substream = NULL; + if (!pdata) + return -EINVAL; + graph_id = cpu_dai->driver->id; + if (pdata->use_reserved_mem) { + ret = snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + component->dev, 0, + pdata->buffer_bytes_max); + if (ret) + return ret; + + return 0; + } + + /* + * Allocate one extra page as a workaround for a DSP bug where 32-bit + * address arithmetic can overflow when the buffer is placed near the + * end of the addressable range. + */ + /* Note: DSP backend dais are uni-directional ONLY(either playback or capture) */ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; @@ -766,7 +1179,8 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc if (ret) return ret; - ret = q6apm_dai_memory_map(component, substream, graph_id, is_push_pull); + ret = q6apm_dai_memory_map(component, substream, graph_id, + is_push_pull, BUFFER_BYTES_MAX); if (ret) return ret; } @@ -774,26 +1188,32 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc return 0; } -static void q6apm_dai_memory_unmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +static int q6apm_dai_memory_unmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_prtd; struct snd_soc_dai *cpu_dai; int graph_id; + int ret; soc_prtd = snd_soc_substream_to_rtd(substream); if (!soc_prtd) - return; + return -EINVAL; cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); if (!cpu_dai) - return; + return -EINVAL; graph_id = cpu_dai->driver->id; - q6apm_unmap_memory_fixed_region(component->dev, graph_id); + ret = q6apm_unmap_memory_fixed_region(component->dev, graph_id); + if (ret) + dev_err(component->dev, + "memory unmap failed: graph=%d ret=%d\n", graph_id, ret); if (q6apm_is_graph_in_push_pull_mode_from_id(component->dev, graph_id, substream->stream)) q6apm_unmap_pos_buffer(component->dev, graph_id); + + return ret; } static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm) @@ -801,12 +1221,16 @@ static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_p struct snd_pcm_substream *substream; substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) + if (substream) { + dev_dbg(component->dev, "pcm_free(): capture memory unmap\n"); q6apm_dai_memory_unmap(component, substream); + } substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - if (substream) + if (substream) { + dev_dbg(component->dev, "pcm_free(): playback memory unmap\n"); q6apm_dai_memory_unmap(component, substream); + } } static int q6apm_dai_compr_open(struct snd_soc_component *component, @@ -1187,18 +1611,78 @@ static int q6apm_dai_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; struct q6apm_dai_data *pdata; struct of_phandle_args args; + struct resource reserved_mem; + size_t required_mem_size = max_t(size_t, BUFFER_BYTES_MIN, + CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE); + u32 src_vmid; int vmids; int rc; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; + pdata->dev = dev; + pdata->buffer_bytes_max = BUFFER_BYTES_MAX; + pdata->aux_mem_addr = Q6APM_STATIC_AUDIO_CARVEOUT_ADDR; + pdata->aux_mem_size = Q6APM_STATIC_AUDIO_CARVEOUT_SIZE; + pdata->aux_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "probe: static aux memory addr=%pa size=%zu\n", + &pdata->aux_mem_addr, pdata->aux_mem_size); rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); if (rc < 0) pdata->sid = -1; else pdata->sid = args.args[0] & SID_MASK_DEFAULT; + dev_dbg(dev, "probe: sid=%lld iommus_rc=%d\n", pdata->sid, rc); + + if (of_property_present(node, "memory-region")) { + rc = of_reserved_mem_region_to_resource(node, 0, &reserved_mem); + if (rc) { + dev_err(dev, "failed to parse reserved memory region: %d\n", rc); + return rc; + } + + rc = of_reserved_mem_device_init_by_idx(dev, node, 0); + if (rc) { + dev_err(dev, "failed to attach reserved memory region: %d\n", rc); + return rc; + } + + pdata->use_reserved_mem = true; + pdata->reserved_mem_addr = reserved_mem.start; + pdata->reserved_mem_size = resource_size(&reserved_mem); + pdata->buffer_bytes_max = min_t(size_t, pdata->reserved_mem_size / 2, + BUFFER_BYTES_MAX); + pdata->buffer_bytes_max = min_t(size_t, pdata->buffer_bytes_max, + Q6APM_RESERVED_BUFFER_BYTES_MAX); + pdata->reserved_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, + "probe: reserved memory addr=%pa size=%zu buffer_bytes_max=%zu\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->buffer_bytes_max); + + rc = devm_add_action_or_reset(dev, + q6apm_dai_release_reserved_memory, pdata); + if (rc) + return rc; + } + + /* + * Default src_vmid to HLOS. Platforms where PCM DMA buffers reside in + * S2-only memory pre-owned by a non-HLOS VMID must override this via + * qcom,src-vmid so qcom_scm_assign_mem() receives the correct srcvm. + */ + pdata->src_vmid = QCOM_SCM_VMID_HLOS; + if (!of_property_read_u32(node, "qcom,src-vmid", &src_vmid)) { + if (src_vmid == 0 || src_vmid > Q6APM_SCM_MAX_VMID) { + dev_err(dev, "qcom,src-vmid=%u out of range [1..%u]\n", + src_vmid, Q6APM_SCM_MAX_VMID); + return -EINVAL; + } + pdata->src_vmid = src_vmid; + dev_dbg(dev, "probe: SCM src_vmid set to 0x%x from DT\n", src_vmid); + } vmids = of_property_count_u32_elems(node, "qcom,vmid"); if (vmids == -EINVAL) { @@ -1236,11 +1720,28 @@ static int q6apm_dai_probe(struct platform_device *pdev) } pdata->num_vmids = vmids; pdata->use_scm_assign = true; + dev_dbg(dev, "probe: SCM assign enabled src_vmid=0x%x num_dst=%d\n", + pdata->src_vmid, pdata->num_vmids); + for (rc = 0; rc < vmids; rc++) + dev_dbg(dev, "probe: SCM dst vmid[%d]=0x%x\n", rc, + pdata->vmids[rc]); } if (pdata->use_scm_assign && !qcom_scm_is_available()) return -EPROBE_DEFER; + if (pdata->use_reserved_mem && pdata->reserved_mem_size < required_mem_size) { + dev_err(dev, "reserved memory size %zu is smaller than required %zu\n", + pdata->reserved_mem_size, required_mem_size); + return -EINVAL; + } + + dev_dbg(dev, + "probe done: use_reserved=%d reserved=%pa/%zu use_scm=%d src_vmid=0x%x num_vmids=%d buffer_bytes_max=%zu\n", + pdata->use_reserved_mem, &pdata->reserved_mem_addr, + pdata->reserved_mem_size, pdata->use_scm_assign, + pdata->src_vmid, pdata->num_vmids, pdata->buffer_bytes_max); + dev_set_drvdata(dev, pdata); return devm_snd_soc_register_component(dev, &q6apm_fe_dai_component, NULL, 0); @@ -1265,3 +1766,4 @@ module_platform_driver(q6apm_dai_platform_driver); MODULE_DESCRIPTION("Q6APM dai driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("DMA_BUF"); From 48daa39a4330fa93ee5e6c6a2322b0bcfb6744b4 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 10 Jun 2026 14:07:57 +0530 Subject: [PATCH 1043/1058] Revert "media: qcom: camss: add support for QCM2390 camss" This reverts commit 45fa97cf9097a8a17e7ada36e3d6b0ef61abc856. Signed-Off-By: Nihal Kumar Gupta --- .../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 2 -- drivers/media/platform/qcom/camss/camss-vfe.c | 1 - drivers/media/platform/qcom/camss/camss.c | 13 ------------- drivers/media/platform/qcom/camss/camss.h | 1 - 4 files changed, 17 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 62208f5c4f17b..dac8d2ecf7995 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1130,7 +1130,6 @@ static bool csiphy_is_gen2(u32 version) switch (version) { case CAMSS_2290: - case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -1223,7 +1222,6 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; case CAMSS_2290: - case CAMSS_2390: case CAMSS_6150: regs->lane_regs = &lane_regs_qcm2290[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index b152f8d48e003..319d191589884 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -342,7 +342,6 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, break; case CAMSS_660: case CAMSS_2290: - case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index f67ecff53f15b..2123f6388e3d7 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5565,18 +5565,6 @@ static const struct camss_resources qcm2290_resources = { .vfe_num = ARRAY_SIZE(vfe_res_2290), }; -static const struct camss_resources qcm2390_resources = { - .version = CAMSS_2390, - .csiphy_res = csiphy_res_2290, - .csid_res = csid_res_2290, - .vfe_res = vfe_res_2290, - .icc_res = icc_res_2290, - .icc_path_num = ARRAY_SIZE(icc_res_2290), - .csiphy_num = ARRAY_SIZE(csiphy_res_2290), - .csid_num = ARRAY_SIZE(csid_res_2290), - .vfe_num = ARRAY_SIZE(vfe_res_2290), -}; - static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", @@ -5764,7 +5752,6 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm670-camss", .data = &sdm670_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, - { .compatible = "qcom,shikra-camss", .data = &qcm2390_resources }, { .compatible = "qcom,sm6150-camss", .data = &sm6150_resources }, { .compatible = "qcom,sm6350-camss", .data = &sm6350_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 8ba8a38113dfc..93d691c8ac63b 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -82,7 +82,6 @@ enum pm_domain { enum camss_version { CAMSS_660, CAMSS_2290, - CAMSS_2390, CAMSS_6150, CAMSS_6350, CAMSS_7280, From 226a710e465831db638426be6974a5a95af7f8e4 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 16 Jun 2026 23:46:51 +0530 Subject: [PATCH 1044/1058] FROMLIST: ASoC: dt-bindings: qcom,apr: Add modem_apps GLINK channel for shikra Add support for the modem_apps GLINK channel on Shikra, as audio processing is handled through the modem DSP. Link: https://lore.kernel.org/all/20260616201315.2565115-2-mohammad.rafi.shaik@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml index e51acdcaafaf6..01250b556985b 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml @@ -120,7 +120,9 @@ allOf: properties: qcom,glink-channels: items: - - const: adsp_apps + - enum: + - adsp_apps + - modem_apps power-domains: false else: properties: From d581cbdae4f92bd7f95b940963f3fe216c2a2be6 Mon Sep 17 00:00:00 2001 From: Harendra Gautam Date: Fri, 5 Jun 2026 16:07:29 +0530 Subject: [PATCH 1045/1058] FROMLIST: MAINTAINERS: Add Qualcomm QAIF driver entry Add MAINTAINERS coverage for the Qualcomm Audio Interface (QAIF) driver so changes to its devicetree binding, CPU DAI driver, and PCM platform driver are routed to the Qualcomm ASoC maintainers and lists. Link: https://lore.kernel.org/all/20260605103739.3557573-4-harendra.gautam@oss.qualcomm.com/ Signed-off-by: Harendra Gautam --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 846d74148fb0a..0135e19bd9cfe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21906,6 +21906,16 @@ F: sound/soc/codecs/wcd93*.* F: sound/soc/codecs/wsa88*.* F: sound/soc/qcom/ +QCOM AUDIO INTERFACE (QAIF) DRIVER +M: Harendra Gautam +M: Srinivas Kandagatla +L: linux-sound@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/sound/qcom,qaif.yaml +F: include/dt-bindings/sound/qcom,qaif.h +F: sound/soc/qcom/qaif* + QCOM EMBEDDED USB DEBUGGER (EUD) M: Souradeep Chowdhury L: linux-arm-msm@vger.kernel.org From fa8c7adac8468dd2ba4e402e05bb4c6706756f34 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Mon, 29 Jun 2026 13:51:20 +0530 Subject: [PATCH 1046/1058] Revert "drm/bridge: Enable LT9611UXD in LT9611C driver" This reverts commit 1876296dd06771b2a157f65982aaf08c584d6771. Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 280 +++++------------------ 1 file changed, 52 insertions(+), 228 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index 4b83322493903..cb584855fd8f0 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -41,13 +41,6 @@ enum lt9611_chip_type { CHIP_LT9611UXD, }; -enum lt9611c_ports { - PORT_SWAP_A = 0, - PORT_SWAP_B, - PORT_SWAP_AB, - PORT_MAX, -}; - struct lt9611c { struct device *dev; struct i2c_client *client; @@ -61,15 +54,12 @@ struct lt9611c { struct mipi_dsi_device *dsi0; struct mipi_dsi_device *dsi1; struct gpio_desc *reset_gpio; - struct gpio_desc *hdmi_gpio; struct regulator_bulk_data supplies[2]; int fw_version; /* Chip variant: C/EX/UXD */ enum lt9611_chip_type chip_type; /* HDMI cable connection status */ bool hdmi_connected; - /* Selected DSI port configuration */ - int selected_port; }; DECLARE_CRC8_TABLE(lt9611c_crc8_table); @@ -107,7 +97,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x01); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x01, 1000, 400 * 1000); + temp == 0x01, 1000, 100 * 1000); if (ret) return -ETIMEDOUT; @@ -117,7 +107,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x02); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x02, 1000, 400 * 1000); + temp == 0x02, 1000, 100 * 1000); if (ret) return -ETIMEDOUT; @@ -125,48 +115,6 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, return_count); } -static int lt9611c_select_port(struct lt9611c *lt9611c, int port_select) -{ - int ret; - u8 set_port_swap_cmd_A[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0xc0}; - u8 set_port_swap_cmd_B[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0x40}; - u8 set_port_swap_cmd_AB[6] = {0x57, 0x4d, 0x31, 0x3a, 0x02, 0xd0}; - u8 set_port_swap_ret[5]; - - if (!lt9611c) - return -EINVAL; - - /* MCU must be running (0xe0ee=0x00) for lt9611c_read_write_flow */ - guard(mutex)(<9611c->ocm_lock); - regmap_write(lt9611c->regmap, 0xe0ee, 0x00); - - switch (port_select) { - case PORT_SWAP_A: - ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_A, - 6, set_port_swap_ret, 5); - if (ret < 0 || set_port_swap_ret[4] == 0) - return ret < 0 ? ret : -EIO; - break; - - case PORT_SWAP_B: - ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_B, - 6, set_port_swap_ret, 5); - if (ret < 0 || set_port_swap_ret[4] == 0) - return ret < 0 ? ret : -EIO; - break; - - case PORT_SWAP_AB: - ret = lt9611c_read_write_flow(lt9611c, set_port_swap_cmd_AB, - 6, set_port_swap_ret, 5); - if (ret < 0 || set_port_swap_ret[4] == 0) - return ret < 0 ? ret : -EIO; - break; - default: - return -EINVAL; - } - return 0; -} - static void lt9611c_config_parameters(struct lt9611c *lt9611c) { const struct reg_sequence seq_write_paras[] = { @@ -488,22 +436,16 @@ static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; u8 data[5]; - mutex_lock(<9611c->ocm_lock); - - /* Ensure MCU is running for HPD status query */ - regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + guard(mutex)(<9611c->ocm_lock); ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); if (ret) { dev_err(dev, "failed to read irq status: %d\n", ret); - mutex_unlock(<9611c->ocm_lock); return IRQ_HANDLED; } - if (!(irq_status & BIT(0))) { - mutex_unlock(<9611c->ocm_lock); + if (!(irq_status & BIT(0))) return IRQ_HANDLED; - } ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); if (ret) { @@ -513,11 +455,10 @@ static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) dev_dbg(dev, "HDMI %s\n", lt9611c->hdmi_connected ? "connected" : "disconnected"); } - regmap_write(lt9611c->regmap, 0xe0df, BIT(0)); + /*Clear interrupt: hardware requires two writes with delay*/ + regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); usleep_range(10000, 12000); - regmap_write(lt9611c->regmap, 0xe0df, 0x00); - - mutex_unlock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); schedule_work(<9611c->work); @@ -678,20 +619,10 @@ static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); int ret; - if (lt9611c->hdmi_gpio) { - gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); - msleep(20); - } -// lt9611c_reset(lt9611c); - - /* Reapply port selection after reset */ - if (lt9611c->selected_port >= 0) { - msleep(200); - ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); - if (ret < 0) - dev_err(lt9611c->dev, "failed to reapply port selection: %d\n", ret); - msleep(200); - } + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + lt9611c_reset(lt9611c); } static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, @@ -724,12 +655,12 @@ static void lt9611c_bridge_atomic_post_disable(struct drm_bridge *bridge, struct drm_atomic_state *state) { struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; - /* Keep chip active for HPD detection */ - mutex_lock(<9611c->ocm_lock); - regmap_write(lt9611c->regmap, 0xe0ee, 0x00); - regmap_write(lt9611c->regmap, 0xe0d0, 0x01); - mutex_unlock(<9611c->ocm_lock); + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); } static enum drm_connector_status @@ -742,10 +673,7 @@ lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; u8 data[5]; - mutex_lock(<9611c->ocm_lock); - - /* Ensure MCU is running for HPD status query */ - regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + guard(mutex)(<9611c->ocm_lock); ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); if (ret) @@ -755,8 +683,6 @@ lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector lt9611c->hdmi_connected = connected; - mutex_unlock(<9611c->ocm_lock); - return connected ? connector_status_connected : connector_status_disconnected; } @@ -851,59 +777,6 @@ static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) return 0; } -static int lt9611c_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge, - const u8 *buffer, size_t len) -{ - struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); - u8 *cmd; - u8 data[5]; - int ret; - - guard(mutex)(<9611c->ocm_lock); - - cmd = kmalloc(5 + len, GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd[0] = 0x57; - cmd[1] = 0x48; - cmd[2] = 0x35; - cmd[3] = 0x3a; - cmd[4] = 0x03;/*write hdmi infoframe*/ - memcpy(cmd + 5, buffer, len); - - ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, - data, ARRAY_SIZE(data)); - kfree(cmd); - - if (ret < 0) { - dev_err(lt9611c->dev, "write hdmi infoframe failed!\n"); - return ret; - } - - return 0; -} - -static int lt9611c_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge) -{ - struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); - u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x03}; - u8 data[5]; - int ret; - - guard(mutex)(<9611c->ocm_lock); - - ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), - data, ARRAY_SIZE(data)); - - if (ret < 0) { - dev_err(lt9611c->dev, "clear hdmi infoframe failed!\n"); - return ret; - } - - return 0; -} - static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, const u8 *buffer, size_t len) { @@ -1022,8 +895,6 @@ static const struct drm_bridge_funcs lt9611c_bridge_funcs = { .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, - .hdmi_write_hdmi_infoframe = lt9611c_hdmi_write_hdmi_infoframe, - .hdmi_clear_hdmi_infoframe = lt9611c_hdmi_clear_hdmi_infoframe, .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, @@ -1053,11 +924,6 @@ static int lt9611c_gpio_init(struct lt9611c *lt9611c) return dev_err_probe(dev, PTR_ERR(lt9611c->reset_gpio), "failed to acquire reset gpio\n"); - lt9611c->hdmi_gpio = devm_gpiod_get_optional(dev, "hdmi", GPIOD_OUT_LOW); - if (IS_ERR(lt9611c->hdmi_gpio)) - return dev_err_probe(dev, PTR_ERR(lt9611c->hdmi_gpio), - "failed to acquire hdmi gpio\n"); - return 0; } @@ -1141,6 +1007,7 @@ static const struct attribute_group *lt9611c_attr_groups[] = { static int lt9611c_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct lt9611c *lt9611c; struct device *dev = &client->dev; bool fw_updated = false; @@ -1157,7 +1024,7 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->dev = dev; lt9611c->client = client; - lt9611c->chip_type = (enum lt9611_chip_type)(uintptr_t)of_device_get_match_data(dev); + lt9611c->chip_type = id->driver_data; ret = devm_mutex_init(dev, <9611c->ocm_lock); if (ret) return dev_err_probe(dev, ret, "failed to init mutex\n"); @@ -1174,13 +1041,15 @@ static int lt9611c_probe(struct i2c_client *client) if (ret < 0) goto err_of_put; - if (lt9611c->hdmi_gpio) { - gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); - msleep(20); - } + ret = lt9611c_regulator_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + goto err_of_put; lt9611c_reset(lt9611c); - msleep(300); lt9611c_lock(lt9611c); @@ -1207,6 +1076,7 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c_unlock(lt9611c); goto err_disable_regulators; } + goto retry; } else { @@ -1218,25 +1088,13 @@ static int lt9611c_probe(struct i2c_client *client) } lt9611c_unlock(lt9611c); - - /* Select port B so the chip is configured for the correct DSI input */ - msleep(200); - ret = lt9611c_select_port(lt9611c, PORT_SWAP_B); - if (ret < 0) { - dev_warn(dev, "port B selection failed (%d), HPD may not work\n", ret); - lt9611c->selected_port = -1; - } else { - lt9611c->selected_port = PORT_SWAP_B; - } - msleep(200); - dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); INIT_WORK(<9611c->work, lt9611c_hpd_work); ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, lt9611c_irq_thread_handler, - IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_AUTOEN, "lt9611c", lt9611c); @@ -1253,20 +1111,6 @@ static int lt9611c_probe(struct i2c_client *client) DRM_BRIDGE_OP_HDMI_AUDIO; lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; - lt9611c->bridge.vendor = "Lontium"; - switch (lt9611c->chip_type) { - case CHIP_LT9611C: - lt9611c->bridge.product = "LT9611C"; - break; - case CHIP_LT9611EX: - lt9611c->bridge.product = "LT9611EX"; - break; - case CHIP_LT9611UXD: - default: - lt9611c->bridge.product = "LT9611UXD"; - break; - } - lt9611c->bridge.hdmi_audio_dev = dev; lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; lt9611c->bridge.hdmi_audio_dai_port = 2; @@ -1291,33 +1135,19 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->hdmi_connected = false; i2c_set_clientdata(client, lt9611c); - - /* Enable HPD interrupt in the chip */ - { - unsigned int irq_status; - - mutex_lock(<9611c->ocm_lock); - regmap_write(lt9611c->regmap, 0xe0ee, 0x01); - regmap_read(lt9611c->regmap, 0xe084, &irq_status); - if (irq_status) { - regmap_write(lt9611c->regmap, 0xe0df, irq_status); - msleep(20); - regmap_write(lt9611c->regmap, 0xe0df, 0x00); - } - regmap_write(lt9611c->regmap, 0xe0d0, 0x01); - regmap_write(lt9611c->regmap, 0xe0ee, 0x00); - mutex_unlock(<9611c->ocm_lock); - } - enable_irq(client->irq); - msleep(100); + lt9611c_reset(lt9611c); return 0; err_remove_bridge: + free_irq(client->irq, lt9611c); cancel_work_sync(<9611c->work); + drm_bridge_remove(<9611c->bridge); err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + err_of_put: of_node_put(lt9611c->dsi1_node); of_node_put(lt9611c->dsi0_node); @@ -1329,11 +1159,9 @@ static void lt9611c_remove(struct i2c_client *client) { struct lt9611c *lt9611c = i2c_get_clientdata(client); - /* - * IRQ was requested with devm_request_threaded_irq and is freed - * automatically by devres — do NOT call free_irq() here. - */ + free_irq(client->irq, lt9611c); cancel_work_sync(<9611c->work); + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); of_node_put(lt9611c->dsi1_node); of_node_put(lt9611c->dsi0_node); } @@ -1341,14 +1169,18 @@ static void lt9611c_remove(struct i2c_client *client) static int lt9611c_bridge_suspend(struct device *dev) { struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; dev_dbg(lt9611c->dev, "suspend\n"); disable_irq(lt9611c->client->irq); + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + return ret; + } gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); - if (lt9611c->hdmi_gpio) - gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 0); - return 0; + return ret; } static int lt9611c_bridge_resume(struct device *dev) @@ -1356,25 +1188,16 @@ static int lt9611c_bridge_resume(struct device *dev) struct lt9611c *lt9611c = dev_get_drvdata(dev); int ret; - if (lt9611c->hdmi_gpio) { - gpiod_set_value_cansleep(lt9611c->hdmi_gpio, 1); - msleep(20); - } - lt9611c_reset(lt9611c); - - /* Reapply port selection after reset, same as atomic_pre_enable */ - if (lt9611c->selected_port >= 0) { - msleep(200); - ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); - if (ret < 0) - dev_warn(lt9611c->dev, "resume: failed to reapply port selection, ret=%d\n", ret); - msleep(200); + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + return ret; } - enable_irq(lt9611c->client->irq); + lt9611c_reset(lt9611c); dev_dbg(lt9611c->dev, "resume\n"); - return 0; + return ret; } static const struct dev_pm_ops lt9611c_bridge_pm_ops = { @@ -1391,9 +1214,9 @@ static struct i2c_device_id lt9611c_id[] = { }; static const struct of_device_id lt9611c_match_table[] = { - { .compatible = "lontium,lt9611c", .data = (void *)CHIP_LT9611C }, - { .compatible = "lontium,lt9611ex", .data = (void *)CHIP_LT9611EX }, - { .compatible = "lontium,lt9611uxd", .data = (void *)CHIP_LT9611UXD }, + { .compatible = "lontium,lt9611c" }, + { .compatible = "lontium,lt9611ex" }, + { .compatible = "lontium,lt9611uxd" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, lt9611c_match_table); @@ -1415,3 +1238,4 @@ MODULE_AUTHOR("SunYun Yang "); MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FW_FILE); + From 4390e7c70c5c99e5ead7c0a7afb2051556584f1d Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Fri, 8 May 2026 21:40:08 +0800 Subject: [PATCH 1047/1058] dt-bindings: bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: - LT9611C: supports 1-port mipi dsi to hdmi 1.4 - LT9611EX: supports 2-port mipi dsi to hdmi 1.4 - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0 Signed-off-by: Sunyun Yang Link: https://patch.msgid.link/20260508134009.4582-2-syyang@lontium.com --- .../bindings/display/bridge/lontium,lt9611.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml index 429a06057ae85..e0821a63d9d74 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -4,19 +4,23 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9611(UXC) 2 Port MIPI to HDMI Bridge +title: Lontium LT9611(UXC/C/EX/UXD) 2 Port MIPI DSI to HDMI Bridge maintainers: - Vinod Koul description: | - The LT9611 and LT9611UXC are bridge devices which convert DSI to HDMI + The LT9611、LT9611UXC、LT9611C、LT9611EX and LT9611UXD + are bridge devices which convert DSI to HDMI properties: compatible: enum: - lontium,lt9611 + - lontium,lt9611c + - lontium,lt9611ex - lontium,lt9611uxc + - lontium,lt9611uxd reg: maxItems: 1 From 54f8736609351f0d6c3c326c00c25434d16181b9 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 11 Jun 2026 02:44:56 +0530 Subject: [PATCH 1048/1058] dt-bindings: brige: lt9611c: add port-select property for LT9611C Add a new optional `lontium,port-select` property to describe the DSI input port configuration for the LT9611C variant, which supports single-port (A or B) and dual-port (A+B) operation. This property allows explicitly selecting the active DSI input port(s): 0 = port A (default) 1 = port B 2 = ports A and B (dual-port) Link: https://patch.msgid.link/20260611-lt9611-b4-send-v1-1-42abbcd3bb1e@oss.qualcomm.com Signed-off-by: Mohit Dsor --- .../bindings/display/bridge/lontium,lt9611.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml index e0821a63d9d74..77220f893bf83 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -41,6 +41,17 @@ properties: vcc-supply: description: Regulator for 3.3V IO power. + lontium,port-select: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + default: 0 + description: | + Selects which DSI input port(s) the bridge uses. Only relevant for + the lontium,lt9611c compatible. + 0 = PORT_SELECT_A - single DSI port A (default) + 1 = PORT_SELECT_B - single DSI port B + 2 = PORT_SELECT_AB - dual DSI ports A and B + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -104,6 +115,8 @@ examples: vdd-supply = <<9611_1v8>; vcc-supply = <<9611_3v3>; + lontium,port-select = <1>; + ports { #address-cells = <1>; #size-cells = <0>; From 0edccbc9343a6e5021b274a9163cc27ad438233b Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 11 Jun 2026 02:44:57 +0530 Subject: [PATCH 1049/1058] drm/bridge: lontium-lt9611c: Increase MCU poll timeout to 200ms The on-chip MCU may take longer than 100ms to respond on some hardware variants or slower I2C buses, causing spurious -ETIMEDOUT errors during normal operation. Double the poll timeout from 100ms to 200ms to improve reliability without changing the poll interval. Link: https://patch.msgid.link/20260611-lt9611-b4-send-v1-2-42abbcd3bb1e@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index cb584855fd8f0..b0402726367e6 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -97,7 +97,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x01); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x01, 1000, 100 * 1000); + temp == 0x01, 1000, 200 * 1000); if (ret) return -ETIMEDOUT; @@ -107,7 +107,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, regmap_write(lt9611c->regmap, 0xe0de, 0x02); ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, - temp == 0x02, 1000, 100 * 1000); + temp == 0x02, 1000, 200 * 1000); if (ret) return -ETIMEDOUT; From 8fa5d41c3a62ab450d0ceedede3daf97f1379f51 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 11 Jun 2026 02:44:58 +0530 Subject: [PATCH 1050/1058] drm-bridge: lontium lt9611c: fixes and improvements Remove two redundant lt9611c_reset() calls: 1. In lt9611c_bridge_atomic_pre_enable(): a reset is already performed during probe and resume; calling it again on every display enable adds ~440ms of unnecessary latency. 2. At the end of lt9611c_probe(): a reset was already performed earlier in probe before lt9611c_lock(). The second reset is redundant. Also, the DRM HDMI bridge framework requires hdmi_write_hdmi_infoframe and hdmi_clear_hdmi_infoframe callbacks for HDMI vendor-specific infoframe (VSI) support, used for features such as HDR metadata signalling. This patch add stub implementations that return success. Wire them into the bridge function table. Also, Store the chip variant enum value in the of_match_table .data field and retrieve it via of_device_get_match_data() when probing from a DT node. Fall back to i2c_device_id.driver_data for non-DT (e.g. ACPI) probe paths. This is the standard kernel pattern for passing per-compatible data through the OF match table, and avoids relying solely on the I2C device ID table for chip type detection when DT is available. Populate bridge.vendor and bridge.product so the DRM HDMI framework can report the correct manufacturer and product name in the HDMI connector properties (visible via xrandr --prop and related sysfs entries). Link: https://patch.msgid.link/20260611-lt9611-b4-send-v1-3-42abbcd3bb1e@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 31 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index b0402726367e6..fe51f49785460 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -622,7 +622,6 @@ static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); if (ret) dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); - lt9611c_reset(lt9611c); } static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, @@ -777,6 +776,17 @@ static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) return 0; } +static int lt9611c_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + return 0; +} + +static int lt9611c_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge) +{ + return 0; +} + static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, const u8 *buffer, size_t len) { @@ -895,6 +905,8 @@ static const struct drm_bridge_funcs lt9611c_bridge_funcs = { .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_hdmi_infoframe = lt9611c_hdmi_write_hdmi_infoframe, + .hdmi_clear_hdmi_infoframe = lt9611c_hdmi_clear_hdmi_infoframe, .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, @@ -1025,6 +1037,13 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->dev = dev; lt9611c->client = client; lt9611c->chip_type = id->driver_data; + + if (dev->of_node) { + lt9611c->chip_type = (uintptr_t)of_device_get_match_data(dev); + } else { + lt9611c->chip_type = id->driver_data; + } + ret = devm_mutex_init(dev, <9611c->ocm_lock); if (ret) return dev_err_probe(dev, ret, "failed to init mutex\n"); @@ -1111,6 +1130,9 @@ static int lt9611c_probe(struct i2c_client *client) DRM_BRIDGE_OP_HDMI_AUDIO; lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + lt9611c->bridge.vendor = "Lontium"; + lt9611c->bridge.product = "LT9611C"; + lt9611c->bridge.hdmi_audio_dev = dev; lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; lt9611c->bridge.hdmi_audio_dai_port = 2; @@ -1136,7 +1158,6 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->hdmi_connected = false; i2c_set_clientdata(client, lt9611c); enable_irq(client->irq); - lt9611c_reset(lt9611c); return 0; @@ -1214,9 +1235,9 @@ static struct i2c_device_id lt9611c_id[] = { }; static const struct of_device_id lt9611c_match_table[] = { - { .compatible = "lontium,lt9611c" }, - { .compatible = "lontium,lt9611ex" }, - { .compatible = "lontium,lt9611uxd" }, + { .compatible = "lontium,lt9611c", .data = (void *)CHIP_LT9611C }, + { .compatible = "lontium,lt9611ex", .data = (void *)CHIP_LT9611EX }, + { .compatible = "lontium,lt9611uxd", .data = (void *)CHIP_LT9611UXD }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, lt9611c_match_table); From e3d93d6b539bb58e51387d7625bf18a3bfcf58fa Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 11 Jun 2026 02:44:59 +0530 Subject: [PATCH 1051/1058] drm/bridge: lontium-lt9611c: Add DSI port selection via DT property Some board designs connect only DSI port B, or both DSI ports A and B, to the LT9611C. Add support for a 'lontium,port-select' DT property that allows the board DTS to specify which DSI port(s) the chip should use: 0 = PORT_SELECT_A (default, single DSI port A) 1 = PORT_SELECT_B (single DSI port B) 2 = PORT_SELECT_AB (dual DSI ports A+B) When the property is absent the driver defaults to PORT_SELECT_A (0), preserving backward compatibility with existing DTS files. The selected port is programmed into the chip via lt9611c_select_port() during probe, after the chip ID has been verified. Link: https://patch.msgid.link/20260611-lt9611-b4-send-v1-4-42abbcd3bb1e@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index fe51f49785460..5d67bb7391fb8 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -41,6 +41,12 @@ enum lt9611_chip_type { CHIP_LT9611UXD, }; +enum lt9611c_PORT_SELECT { + PORT_SELECT_A = 0, + PORT_SELECT_B = 1, + PORT_SELECT_AB = 2, +}; + struct lt9611c { struct device *dev; struct i2c_client *client; @@ -60,6 +66,8 @@ struct lt9611c { enum lt9611_chip_type chip_type; /* HDMI cable connection status */ bool hdmi_connected; + /* Selected DSI port configuration */ + int selected_port; }; DECLARE_CRC8_TABLE(lt9611c_crc8_table); @@ -115,6 +123,34 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, return_count); } +static int lt9611c_select_port(struct lt9611c *lt9611c, int port_select) +{ + int ret; + u8 set_port_select_cmd[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0xc0}; + u8 set_port_select_ret[5]; + + if (port_select == PORT_SELECT_B) { + set_port_select_cmd[5] = 0x40; + } else if (port_select == PORT_SELECT_AB) { + set_port_select_cmd[4] = 0x02; + set_port_select_cmd[5] = 0xd0; + } else if (port_select != PORT_SELECT_A) { + return -EINVAL; + } + + /* MCU must be running (0xe0ee=0x00) for lt9611c_read_write_flow */ + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, set_port_select_cmd, + ARRAY_SIZE(set_port_select_cmd), + set_port_select_ret, + ARRAY_SIZE(set_port_select_ret)); + if (ret < 0 || set_port_select_ret[4] == 0) + return ret < 0 ? ret : -EIO; + + return 0; +} + static void lt9611c_config_parameters(struct lt9611c *lt9611c) { const struct reg_sequence seq_write_paras[] = { @@ -924,6 +960,10 @@ static int lt9611c_parse_dt(struct device *dev, lt9611c->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + if (of_property_read_u32(dev->of_node, "lontium,port-select", + <9611c->selected_port)) + lt9611c->selected_port = 0; + return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); } @@ -1070,6 +1110,10 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c_reset(lt9611c); + ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); + if (ret < 0) + dev_err(lt9611c->dev, "failed to select port %d\n", lt9611c->selected_port); + lt9611c_lock(lt9611c); ret = lt9611c_read_chipid(lt9611c); From ad44cdc5ad563192dfe943b1a87efeb1e217d1d2 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Sun, 28 Jun 2026 02:34:37 +0530 Subject: [PATCH 1052/1058] drm/bridge: lt9611c: fallback to cached HPD status on read failure HPD status is retrieved via an MCU command. In some cases the command may fail, for example when the MCU is not yet ready, leading to incorrect disconnect reporting. Instead of returning an error state, fall back to the last known HPD status to provide a more stable detection result. This avoids spurious disconnect events during initialization. Link: https://patch.msgid.link/20260628-hpd_stable-v1-1-13d8b732c4c6@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index 5d67bb7391fb8..81ca9d62eae37 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -711,10 +711,12 @@ lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector guard(mutex)(<9611c->ocm_lock); ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); - if (ret) + if (ret) { dev_err(dev, "failed to read HPD status (err=%d)\n", ret); - else + connected = lt9611c->hdmi_connected; + } else { connected = (data[4] == 0x02); + } lt9611c->hdmi_connected = connected; From fa0ccd1ef7c5dbaa3831b75655e4d94ac6272c6a Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Sun, 28 Jun 2026 02:34:38 +0530 Subject: [PATCH 1053/1058] drm/bridge: lt9611c: implement hpd_enable callback Implement the .hpd_enable callback to trigger HPD status update and schedule event propagation. Link: https://patch.msgid.link/20260628-hpd_stable-v1-2-13d8b732c4c6@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index 81ca9d62eae37..30a07e97626aa 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -923,6 +923,23 @@ static void lt9611c_hdmi_audio_shutdown(struct drm_bridge *bridge, drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); } +static void lt9611c_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + int ret; + + mutex_lock(<9611c->ocm_lock); + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + if (!ret) + lt9611c->hdmi_connected = (data[4] == 0x02); + mutex_unlock(<9611c->ocm_lock); + + schedule_work(<9611c->work); +} + static int lt9611c_hdmi_audio_startup(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -939,6 +956,7 @@ static const struct drm_bridge_funcs lt9611c_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, + .hpd_enable = lt9611c_bridge_hpd_enable, .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, From be2e5140478e0089b636a7bf8fb9047370186a41 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Sun, 28 Jun 2026 02:34:39 +0530 Subject: [PATCH 1054/1058] drm/bridge: lt9611c: fix DT parsing and bridge refcount Ensure DT nodes are properly released on error and acquire a reference to next_bridge Link: https://patch.msgid.link/20260628-hpd_stable-v1-3-13d8b732c4c6@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index 30a07e97626aa..4c8a3829a4bed 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -974,6 +974,8 @@ static const struct drm_bridge_funcs lt9611c_bridge_funcs = { static int lt9611c_parse_dt(struct device *dev, struct lt9611c *lt9611c) { + int ret; + lt9611c->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); if (!lt9611c->dsi0_node) return dev_err_probe(dev, -ENODEV, "failed to get remote node for primary dsi\n"); @@ -984,7 +986,14 @@ static int lt9611c_parse_dt(struct device *dev, <9611c->selected_port)) lt9611c->selected_port = 0; - return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); + if (ret) { + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); + return ret; + } + drm_bridge_get(lt9611c->bridge.next_bridge); + return 0; } static int lt9611c_gpio_init(struct lt9611c *lt9611c) From 750c4874380d61d8b37f83c7fac34bfe56aa837b Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Sun, 28 Jun 2026 02:34:40 +0530 Subject: [PATCH 1055/1058] drm/bridge: lt9611c: fix chip type initialization Remove redundant assignment of chip_type from I2C match as it is derived from DT data when available. Link: https://patch.msgid.link/20260628-hpd_stable-v1-4-13d8b732c4c6@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index 4c8a3829a4bed..d35a246e2d011 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -1105,7 +1105,6 @@ static int lt9611c_probe(struct i2c_client *client) lt9611c->dev = dev; lt9611c->client = client; - lt9611c->chip_type = id->driver_data; if (dev->of_node) { lt9611c->chip_type = (uintptr_t)of_device_get_match_data(dev); From f5654fe87079b83cd2bfc1a4bf10a7bf331ad4dd Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Sun, 28 Jun 2026 02:34:41 +0530 Subject: [PATCH 1056/1058] drm/bridge: lt9611c: clean up probe error and remove paths Remove redundant cleanup of IRQ and bridge resources. Link: https://patch.msgid.link/20260628-hpd_stable-v1-5-13d8b732c4c6@oss.qualcomm.com Signed-off-by: Mohit Dsor --- drivers/gpu/drm/bridge/lontium-lt9611c.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c index d35a246e2d011..30828bb9b3b85 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611c.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -1234,9 +1234,7 @@ static int lt9611c_probe(struct i2c_client *client) return 0; err_remove_bridge: - free_irq(client->irq, lt9611c); cancel_work_sync(<9611c->work); - drm_bridge_remove(<9611c->bridge); err_disable_regulators: regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); @@ -1252,7 +1250,6 @@ static void lt9611c_remove(struct i2c_client *client) { struct lt9611c *lt9611c = i2c_get_clientdata(client); - free_irq(client->irq, lt9611c); cancel_work_sync(<9611c->work); regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); of_node_put(lt9611c->dsi1_node); From e6da759870c85255263830048e5567d47dab3978 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 3 Jul 2026 17:35:38 +0530 Subject: [PATCH 1057/1058] arm64: dts: qcom: shikra: Add missing CPU OPPs Add the 2.208 GHz operating point to the CPU0 and CPU3 OPP tables, and add the 768 MHz operating point to the CPU3 table. This keeps the Shikra CPU OPP tables aligned with the supported frequency set. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 4fbad7b6007e2..0809afc65e0ef 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -252,12 +252,22 @@ opp-hz = /bits/ 64 <1804800000>; opp-peak-kBps = <7216000 43622400>; }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-peak-kBps = <7216000 43622400>; + }; }; cpu3_opp_table: opp-table-cpu3 { compatible = "operating-points-v2"; opp-shared; + opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + opp-peak-kBps = <1200000 17817600>; + }; + opp-1017600000 { opp-hz = /bits/ 64 <1017600000>; opp-peak-kBps = <2188000 25804800>; @@ -282,6 +292,11 @@ opp-hz = /bits/ 64 <1900800000>; opp-peak-kBps = <7216000 43622400>; }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-peak-kBps = <7216000 43622400>; + }; }; pmu-a55 { From c0115db91e13a0d5911e8e64ea6d90194a7f50e6 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 3 Jul 2026 18:14:31 +0530 Subject: [PATCH 1058/1058] Add qcom-next log files for 20260703 Adding merge log file and topic_SHA1 file Signed-off-by: Salendarsingh Gaud --- qcom-next/merge.log | 485 +++++++++++++++++++++++++++++++++++++++++++ qcom-next/topic_SHA1 | 42 ++++ 2 files changed, 527 insertions(+) create mode 100644 qcom-next/merge.log create mode 100644 qcom-next/topic_SHA1 diff --git a/qcom-next/merge.log b/qcom-next/merge.log new file mode 100644 index 0000000000000..9e6791e753ee8 --- /dev/null +++ b/qcom-next/merge.log @@ -0,0 +1,485 @@ +Verified existence of local and remote repos: Success +/local/mnt/workspace/sgaud/Builds/Github/All_Runners/kernel-automation/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics /local/mnt/workspace/sgaud/Builds/Github/All_Runners/kernel-automation/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics +Reuse-Recorded-Resolution: Enabled +Downloaded shared rerere cache +Local tree is clean +Removing old remotes ... +The remote kernel https://github.com/qualcomm-linux/kernel.git is no longer tracked. +Delete it [Y/n]? The remote origin https://github.com/qualcomm-linux/kernel-topics.git is no longer tracked. +Delete it [Y/n]? The remote trovalds https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git is no longer tracked. +Delete it [Y/n]? Done, removed 3 old remote(s). +Adding new remotes... +Adding remote baseline https://github.com/qualcomm-linux/kernel.git qcom-next-staging +Updating baseline +Adding remote tech/bsp/clk https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/clk +Updating tech/bsp/clk +Adding remote tech/bsp/devfreq https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/devfreq +Updating tech/bsp/devfreq +Adding remote tech/bsp/ec https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/ec +Updating tech/bsp/ec +Adding remote tech/bsp/interconnect https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/interconnect +Updating tech/bsp/interconnect +Adding remote tech/mem/secure-buffer https://github.com/qualcomm-linux/kernel-topics.git tech/mem/secure-buffer +Updating tech/mem/secure-buffer +Adding remote tech/security/firmware-smc https://github.com/qualcomm-linux/kernel-topics.git tech/security/firmware-smc +Updating tech/security/firmware-smc +Adding remote tech/bsp/soc-infra https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/soc-infra +Updating tech/bsp/soc-infra +Adding remote tech/debug/soc https://github.com/qualcomm-linux/kernel-topics.git tech/debug/soc +Updating tech/debug/soc +Adding remote tech/bsp/pinctrl https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/pinctrl +Updating tech/bsp/pinctrl +Adding remote tech/bsp/remoteproc https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/remoteproc +Updating tech/bsp/remoteproc +Adding remote tech/bus/peripherals https://github.com/qualcomm-linux/kernel-topics.git tech/bus/peripherals +Updating tech/bus/peripherals +Adding remote tech/bus/pci/all https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/all +Updating tech/bus/pci/all +Adding remote tech/bus/pci/mhi https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/mhi +Updating tech/bus/pci/mhi +Adding remote tech/bus/pci/phy https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/phy +Updating tech/bus/pci/phy +Adding remote tech/bus/pci/pwrctl https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/pwrctl +Updating tech/bus/pci/pwrctl +Adding remote tech/bus/usb/dwc https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/dwc +Updating tech/bus/usb/dwc +Adding remote tech/bus/usb/gadget https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/gadget +Updating tech/bus/usb/gadget +Adding remote tech/bus/usb/phy https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/phy +Updating tech/bus/usb/phy +Adding remote tech/debug/eud https://github.com/qualcomm-linux/kernel-topics.git tech/debug/eud +Updating tech/debug/eud +Adding remote tech/debug/hwtracing https://github.com/qualcomm-linux/kernel-topics.git tech/debug/hwtracing +Updating tech/debug/hwtracing +Adding remote tech/debug/rdbg https://github.com/qualcomm-linux/kernel-topics.git tech/debug/rdbg +Updating tech/debug/rdbg +Adding remote tech/pmic/backlight https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/backlight +Updating tech/pmic/backlight +Adding remote tech/pmic/mfd https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/mfd +Updating tech/pmic/mfd +Adding remote tech/pmic/misc https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/misc +Updating tech/pmic/misc +Adding remote tech/pmic/regulator https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/regulator +Updating tech/pmic/regulator +Adding remote tech/pmic/supply https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/supply +Updating tech/pmic/supply +Adding remote tech/mem/dma-buf https://github.com/qualcomm-linux/kernel-topics.git tech/mem/dma-buf +Updating tech/mem/dma-buf +Adding remote tech/mem/iommu https://github.com/qualcomm-linux/kernel-topics.git tech/mem/iommu +Updating tech/mem/iommu +Adding remote tech/mm/audio/all https://github.com/qualcomm-linux/kernel-topics.git tech/mm/audio/all +Updating tech/mm/audio/all +Adding remote tech/mm/audio/soundwire https://github.com/qualcomm-linux/kernel-topics.git tech/mm/audio/soundwire +Updating tech/mm/audio/soundwire +Adding remote tech/mm/camss https://github.com/qualcomm-linux/kernel-topics.git tech/mm/camss +Updating tech/mm/camss +Adding remote tech/mm/drm https://github.com/qualcomm-linux/kernel-topics.git tech/mm/drm +Updating tech/mm/drm +Adding remote tech/mm/fastrpc https://github.com/qualcomm-linux/kernel-topics.git tech/mm/fastrpc +Updating tech/mm/fastrpc +Adding remote tech/mm/phy https://github.com/qualcomm-linux/kernel-topics.git tech/mm/phy +Updating tech/mm/phy +Adding remote tech/mm/video https://github.com/qualcomm-linux/kernel-topics.git tech/mm/video +Updating tech/mm/video +Adding remote tech/mm/gpu https://github.com/qualcomm-linux/kernel-topics.git tech/mm/gpu +Updating tech/mm/gpu +Adding remote tech/mproc/rpmsg https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/rpmsg +Updating tech/mproc/rpmsg +Adding remote tech/mproc/qmi https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/qmi +Updating tech/mproc/qmi +Adding remote tech/net/ath https://github.com/qualcomm-linux/kernel-topics.git tech/net/ath +Updating tech/net/ath +Adding remote tech/net/eth https://github.com/qualcomm-linux/kernel-topics.git tech/net/eth +Updating tech/net/eth +Adding remote tech/net/rmnet https://github.com/qualcomm-linux/kernel-topics.git tech/net/rmnet +Updating tech/net/rmnet +Adding remote tech/net/qrtr https://github.com/qualcomm-linux/kernel-topics.git tech/net/qrtr +Updating tech/net/qrtr +Adding remote tech/net/phy https://github.com/qualcomm-linux/kernel-topics.git tech/net/phy +Updating tech/net/phy +Adding remote tech/net/bluetooth https://github.com/qualcomm-linux/kernel-topics.git tech/net/bluetooth +Updating tech/net/bluetooth +Adding remote tech/pm/opp https://github.com/qualcomm-linux/kernel-topics.git tech/pm/opp +Updating tech/pm/opp +Adding remote tech/pm/pmdomain https://github.com/qualcomm-linux/kernel-topics.git tech/pm/pmdomain +Updating tech/pm/pmdomain +Adding remote tech/pm/power https://github.com/qualcomm-linux/kernel-topics.git tech/pm/power +Updating tech/pm/power +Adding remote tech/pm/thermal https://github.com/qualcomm-linux/kernel-topics.git tech/pm/thermal +Updating tech/pm/thermal +Adding remote tech/security/crypto https://github.com/qualcomm-linux/kernel-topics.git tech/security/crypto +Updating tech/security/crypto +Adding remote tech/security/fscrypt https://github.com/qualcomm-linux/kernel-topics.git tech/security/fscrypt +Updating tech/security/fscrypt +Adding remote tech/security/ice https://github.com/qualcomm-linux/kernel-topics.git tech/security/ice +Updating tech/security/ice +Adding remote tech/storage/nvmem https://github.com/qualcomm-linux/kernel-topics.git tech/storage/nvmem +Updating tech/storage/nvmem +Adding remote tech/storage/phy https://github.com/qualcomm-linux/kernel-topics.git tech/storage/phy +Updating tech/storage/phy +Adding remote tech/storage/all https://github.com/qualcomm-linux/kernel-topics.git tech/storage/all +Updating tech/storage/all +Adding remote tech/virt/gunyah https://github.com/qualcomm-linux/kernel-topics.git tech/virt/gunyah +Updating tech/virt/gunyah +Adding remote tech/all/dt/qcs6490 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs6490 +Updating tech/all/dt/qcs6490 +Adding remote tech/all/dt/qcs9100 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs9100 +Updating tech/all/dt/qcs9100 +Adding remote tech/all/dt/qcs8300 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs8300 +Updating tech/all/dt/qcs8300 +Adding remote tech/all/dt/qcs615 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs615 +Updating tech/all/dt/qcs615 +Adding remote tech/all/dt/agatti https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/agatti +Updating tech/all/dt/agatti +Adding remote tech/all/dt/hamoa https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/hamoa +Updating tech/all/dt/hamoa +Adding remote tech/all/dt/glymur https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/glymur +Updating tech/all/dt/glymur +Adding remote tech/all/dt/kaanapali https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/kaanapali +Updating tech/all/dt/kaanapali +Adding remote tech/all/dt/pakala https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/pakala +Updating tech/all/dt/pakala +Adding remote tech/all/config https://github.com/qualcomm-linux/kernel-topics.git tech/all/config +Updating tech/all/config +Adding remote tech/overlay/dt https://github.com/qualcomm-linux/kernel-topics.git tech/overlay/dt +Updating tech/overlay/dt +Adding remote tech/all/workaround https://github.com/qualcomm-linux/kernel-topics.git tech/all/workaround +Updating tech/all/workaround +Adding remote tech/mproc/all https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/all +Updating tech/mproc/all +Adding remote tech/noup/debug/all https://github.com/qualcomm-linux/kernel-topics.git tech/noup/debug/all +Updating tech/noup/debug/all +Adding remote tech/hwe/unoq https://github.com/qualcomm-linux/kernel-topics.git tech/hwe/unoq +Updating tech/hwe/unoq +Adding remote early/hwe/shikra/drivers https://github.com/qualcomm-linux/kernel-topics.git early/hwe/shikra/drivers +Updating early/hwe/shikra/drivers +Adding remote early/hwe/shikra/dt https://github.com/qualcomm-linux/kernel-topics.git early/hwe/shikra/dt +Updating early/hwe/shikra/dt +Done, added 73 new remote(s). +Updating the remotes ... +Updating tech/bsp/clk +Updating tech/bsp/devfreq +Updating tech/bsp/ec +Updating tech/bsp/interconnect +Updating tech/mem/secure-buffer +Updating tech/security/firmware-smc +Updating tech/bsp/soc-infra +Updating tech/debug/soc +Updating tech/bsp/pinctrl +Updating tech/bsp/remoteproc +Updating tech/bus/peripherals +Updating tech/bus/pci/all +Updating tech/bus/pci/mhi +Updating tech/bus/pci/phy +Updating tech/bus/pci/pwrctl +Updating tech/bus/usb/dwc +Updating tech/bus/usb/gadget +Updating tech/bus/usb/phy +Updating tech/debug/eud +Updating tech/debug/hwtracing +Updating tech/debug/rdbg +Updating tech/pmic/backlight +Updating tech/pmic/mfd +Updating tech/pmic/misc +Updating tech/pmic/regulator +Updating tech/pmic/supply +Updating tech/mem/dma-buf +Updating tech/mem/iommu +Updating tech/mm/audio/all +Updating tech/mm/audio/soundwire +Updating tech/mm/camss +Updating tech/mm/drm +Updating tech/mm/fastrpc +Updating tech/mm/phy +Updating tech/mm/video +Updating tech/mm/gpu +Updating tech/mproc/rpmsg +Updating tech/mproc/qmi +Updating tech/net/ath +Updating tech/net/eth +Updating tech/net/rmnet +Updating tech/net/qrtr +Updating tech/net/phy +Updating tech/net/bluetooth +Updating tech/pm/opp +Updating tech/pm/pmdomain +Updating tech/pm/power +Updating tech/pm/thermal +Updating tech/security/crypto +Updating tech/security/fscrypt +Updating tech/security/ice +Updating tech/storage/nvmem +Updating tech/storage/phy +Updating tech/storage/all +Updating tech/virt/gunyah +Updating tech/all/dt/qcs6490 +Updating tech/all/dt/qcs9100 +Updating tech/all/dt/qcs8300 +Updating tech/all/dt/qcs615 +Updating tech/all/dt/agatti +Updating tech/all/dt/hamoa +Updating tech/all/dt/glymur +Updating tech/all/dt/kaanapali +Updating tech/all/dt/pakala +Updating tech/all/config +Updating tech/overlay/dt +Updating tech/all/workaround +Updating tech/mproc/all +Updating tech/noup/debug/all +Updating tech/hwe/unoq +Updating early/hwe/shikra/drivers +Updating early/hwe/shikra/dt +Done, updated 0 remote(s). +Updating baseline ... +Fetching baseline +latest tag/id is dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Done, updated baseline. +Latest tag is dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Create a new integration branch based on dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Merging topic branches... +------------------------------------------ + ** Merging topic branch: tech/bsp/clk/tech/bsp/clk +Merge successful : tech/bsp/clk : dcf6518b860209e2608f9cb22081f829ab7b43d4 : 22 +------------------------------------------ + ** Merging topic branch: tech/bsp/devfreq/tech/bsp/devfreq +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/ec/tech/bsp/ec +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/interconnect/tech/bsp/interconnect +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/secure-buffer/tech/mem/secure-buffer +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/firmware-smc/tech/security/firmware-smc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/soc-infra/tech/bsp/soc-infra +Merge successful : tech/bsp/soc-infra : 600ea9c656eedd9961e311ec6c0c252ed046221f : 24 +------------------------------------------ + ** Merging topic branch: tech/debug/soc/tech/debug/soc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/pinctrl/tech/bsp/pinctrl +Merge successful : tech/bsp/pinctrl : 79149ef6a826d6237346aa74eca65ccbe19d761f : 1 +------------------------------------------ + ** Merging topic branch: tech/bsp/remoteproc/tech/bsp/remoteproc +Merge successful : tech/bsp/remoteproc : ce284eea5fbde6dd880cb8e90df6b044a01d0256 : 9 +------------------------------------------ + ** Merging topic branch: tech/bus/peripherals/tech/bus/peripherals +Merge successful : tech/bus/peripherals : fedd8c628af7b28992224012386fec13483c514c : 6 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/all/tech/bus/pci/all +Merge successful : tech/bus/pci/all : ebd808fbc5fcd2b79e89bec0a311f7bb417b020c : 4 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/mhi/tech/bus/pci/mhi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/pci/phy/tech/bus/pci/phy +Merge successful : tech/bus/pci/phy : ec405c892a7bede96799f42453a4e0281fad9447 : 4 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/pwrctl/tech/bus/pci/pwrctl +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/dwc/tech/bus/usb/dwc +Merge successful : tech/bus/usb/dwc : 9dd47ad7e5c1dea9cfbcdd3f5e84af8d647af95f : 3 +------------------------------------------ + ** Merging topic branch: tech/bus/usb/gadget/tech/bus/usb/gadget +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/phy/tech/bus/usb/phy +Merge successful : tech/bus/usb/phy : c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 : 35 +------------------------------------------ + ** Merging topic branch: tech/debug/eud/tech/debug/eud +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/debug/hwtracing/tech/debug/hwtracing +Merge successful : tech/debug/hwtracing : ee4a490ad48a7236b3f417efda48cc1393d2e0d9 : 31 +------------------------------------------ + ** Merging topic branch: tech/debug/rdbg/tech/debug/rdbg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/backlight/tech/pmic/backlight +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/mfd/tech/pmic/mfd +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/misc/tech/pmic/misc +Merge successful : tech/pmic/misc : 6fb618c321fd27ccf873f5b4bc6737baee8fd8bb : 8 +------------------------------------------ + ** Merging topic branch: tech/pmic/regulator/tech/pmic/regulator +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/supply/tech/pmic/supply +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/dma-buf/tech/mem/dma-buf +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/iommu/tech/mem/iommu +Merge successful : tech/mem/iommu : 44df12a52b9e962122cf7f6253ca1d6d3f2da862 : 8 +------------------------------------------ + ** Merging topic branch: tech/mm/audio/all/tech/mm/audio/all +Merge successful : tech/mm/audio/all : 88b8f29570c5211e654cec357e6a1282f92737b7 : 8 +------------------------------------------ + ** Merging topic branch: tech/mm/audio/soundwire/tech/mm/audio/soundwire +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/camss/tech/mm/camss +Merge successful : tech/mm/camss : c394dfb4b3768df4d41b9b32bf310c307451fa68 : 32 +------------------------------------------ + ** Merging topic branch: tech/mm/drm/tech/mm/drm +Merge successful : tech/mm/drm : b480a075f51d506402f8a081a271e5e05896986e : 65 +------------------------------------------ + ** Merging topic branch: tech/mm/fastrpc/tech/mm/fastrpc +Merge successful : tech/mm/fastrpc : e014e351825ea08a7a6ba61f4c005cf1aebcb147 : 11 +------------------------------------------ + ** Merging topic branch: tech/mm/phy/tech/mm/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/video/tech/mm/video +Merge successful : tech/mm/video : dc89f72844c066088e5d47e5efa9e32589b2959d : 32 +------------------------------------------ + ** Merging topic branch: tech/mm/gpu/tech/mm/gpu +Merge successful : tech/mm/gpu : 4433b066ef8096363c84ab1e9fc6f71e465ac95f : 6 +------------------------------------------ + ** Merging topic branch: tech/mproc/rpmsg/tech/mproc/rpmsg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mproc/qmi/tech/mproc/qmi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/ath/tech/net/ath +Merge successful : tech/net/ath : a91544020bd06f83313c1544f2f94d7c19064843 : 14 +------------------------------------------ + ** Merging topic branch: tech/net/eth/tech/net/eth +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/rmnet/tech/net/rmnet +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/qrtr/tech/net/qrtr +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/phy/tech/net/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/bluetooth/tech/net/bluetooth +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/opp/tech/pm/opp +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/pmdomain/tech/pm/pmdomain +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/power/tech/pm/power +Merge successful : tech/pm/power : bb887016f3998f14184b38d1ae3ced78a6d80567 : 13 +------------------------------------------ + ** Merging topic branch: tech/pm/thermal/tech/pm/thermal +Merge failed, manual merge +No files need merging +[qcom-next fdc65996002d] Merge remote-tracking branch tech/pm/thermal into qcom-next +Merge successful : tech/pm/thermal : d36b3ee3b5ce84165d974c7141b15c3b6a283691 : 7 +------------------------------------------ + ** Merging topic branch: tech/security/crypto/tech/security/crypto +Merge successful : tech/security/crypto : c36112e9987659986a3171f206e4c4a05932fb8b : 14 +------------------------------------------ + ** Merging topic branch: tech/security/fscrypt/tech/security/fscrypt +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/ice/tech/security/ice +Merge successful : tech/security/ice : beabac03036a596434bb02c3f91b7c9672ea7c15 : 9 +------------------------------------------ + ** Merging topic branch: tech/storage/nvmem/tech/storage/nvmem +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/phy/tech/storage/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/all/tech/storage/all +Merge successful : tech/storage/all : d86d915355ae0f4d79ec0223864f41cb1c30ab70 : 4 +------------------------------------------ + ** Merging topic branch: tech/virt/gunyah/tech/virt/gunyah +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs6490/tech/all/dt/qcs6490 +Merge successful : tech/all/dt/qcs6490 : d70580362b1b5c9d8db75e08b810c8a9c8358fc3 : 21 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs9100/tech/all/dt/qcs9100 +Merge successful : tech/all/dt/qcs9100 : 3853a4908bb4a047bb6d096a83ca28de504b56ac : 91 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs8300/tech/all/dt/qcs8300 +Merge failed, manual merge +No files need merging +[qcom-next 82d075244dbc] Merge remote-tracking branch tech/all/dt/qcs8300 into qcom-next +Merge successful : tech/all/dt/qcs8300 : e93aa15800b0cebedc8e0d79e5cf39fb32616e48 : 24 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs615/tech/all/dt/qcs615 +Merge successful : tech/all/dt/qcs615 : 1cc303d042350bbb1e4fc4494c33356769995308 : 8 +------------------------------------------ + ** Merging topic branch: tech/all/dt/agatti/tech/all/dt/agatti +Merge successful : tech/all/dt/agatti : c828f10cd2c53b7ff2cc061e73b239973ee17bc6 : 1 +------------------------------------------ + ** Merging topic branch: tech/all/dt/hamoa/tech/all/dt/hamoa +Merge successful : tech/all/dt/hamoa : 723e3ef44a909d5e2a4b270d6bccdbeec975b9d1 : 32 +------------------------------------------ + ** Merging topic branch: tech/all/dt/glymur/tech/all/dt/glymur +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/kaanapali/tech/all/dt/kaanapali +Merge successful : tech/all/dt/kaanapali : f6ed56b503a15dc168700ec4f02e0365680c2cf4 : 20 +------------------------------------------ + ** Merging topic branch: tech/all/dt/pakala/tech/all/dt/pakala +Merge successful : tech/all/dt/pakala : b2e5e9630f3ff8f681ae77aaab3ef852c4896df4 : 12 +------------------------------------------ + ** Merging topic branch: tech/all/config/tech/all/config +Merge successful : tech/all/config : 2f8abb9a606bd9d9194983ee7ed3d0a4ee20bca2 : 69 +------------------------------------------ + ** Merging topic branch: tech/overlay/dt/tech/overlay/dt +Merge failed, manual merge +No files need merging +[qcom-next 158b9354ca96] Merge remote-tracking branch tech/overlay/dt into qcom-next +Merge successful : tech/overlay/dt : cb96f0691662ec18e92c2cbc483351e4ebdf11f5 : 68 +------------------------------------------ + ** Merging topic branch: tech/all/workaround/tech/all/workaround +Merge failed, manual merge +No files need merging +[qcom-next 355e6d4a5ebe] Merge remote-tracking branch tech/all/workaround into qcom-next +Merge successful : tech/all/workaround : ecc126013f9aac2681125eddbe60f7fa40beeaa3 : 26 +------------------------------------------ + ** Merging topic branch: tech/mproc/all/tech/mproc/all +Merge failed, manual merge +No files need merging +[qcom-next 2efc0ed28481] Merge remote-tracking branch tech/mproc/all into qcom-next +Merge successful : tech/mproc/all : 0aa90b7d45babe6116bcbb3006ae4636256b6e0f : 3 +------------------------------------------ + ** Merging topic branch: tech/noup/debug/all/tech/noup/debug/all +Merge successful : tech/noup/debug/all : cbdd4bbfa24a682d76769d4c1c66bb67b262ae4d : 26 +------------------------------------------ + ** Merging topic branch: tech/hwe/unoq/tech/hwe/unoq +Merge successful : tech/hwe/unoq : a2d85fe547167dbd8fc59618907c20a6f17d2e5a : 4 +------------------------------------------ + ** Merging topic branch: early/hwe/shikra/drivers/early/hwe/shikra/drivers +Merge failed, manual merge +No files need merging +[qcom-next 272c95718d75] Merge remote-tracking branch early/hwe/shikra/drivers into qcom-next +Merge successful : early/hwe/shikra/drivers : f5654fe87079b83cd2bfc1a4bf10a7bf331ad4dd : 160 +------------------------------------------ + ** Merging topic branch: early/hwe/shikra/dt/early/hwe/shikra/dt +Merge failed, manual merge +No files need merging +[qcom-next 4a8a9a0d0fba] Merge remote-tracking branch early/hwe/shikra/dt into qcom-next +Merge successful : early/hwe/shikra/dt : e6da759870c85255263830048e5567d47dab3978 : 122 +Done, merged 40 topic(s). +[main 76354b9] New rr-cache entries from ci-merge + 6 files changed, 5881 insertions(+) + create mode 100644 rr-cache/28bf2625415bd45915fcc4a076558f1eccd39540/thisimage.1 + create mode 100644 rr-cache/3d29194c00c402d7c6a76bd9cc81b2073a0ca7ca/thisimage + create mode 100644 rr-cache/4fb584f263e8b86ac32435d904fb9214c658e52d/thisimage + create mode 100644 rr-cache/9d75e91f6e0a77bd894803a54fa46add0b1f02bb/thisimage + create mode 100644 rr-cache/a1639217f5ed352a58fadd68737220f3dfe1a41e/thisimage + create mode 100644 rr-cache/f75781ed0106a815e457aedd5c00b62d10357272/thisimage diff --git a/qcom-next/topic_SHA1 b/qcom-next/topic_SHA1 new file mode 100644 index 0000000000000..335a1f094ec65 --- /dev/null +++ b/qcom-next/topic_SHA1 @@ -0,0 +1,42 @@ +Name SHA Commits +------------------------------------------------------------------------------------ +tech/bsp/clk dcf6518b860209e2608f9cb22081f829ab7b43d4 22 +tech/bsp/soc-infra 600ea9c656eedd9961e311ec6c0c252ed046221f 24 +tech/bsp/pinctrl 79149ef6a826d6237346aa74eca65ccbe19d761f 1 +tech/bsp/remoteproc ce284eea5fbde6dd880cb8e90df6b044a01d0256 9 +tech/bus/peripherals fedd8c628af7b28992224012386fec13483c514c 6 +tech/bus/pci/all ebd808fbc5fcd2b79e89bec0a311f7bb417b020c 4 +tech/bus/pci/phy ec405c892a7bede96799f42453a4e0281fad9447 4 +tech/bus/usb/dwc 9dd47ad7e5c1dea9cfbcdd3f5e84af8d647af95f 3 +tech/bus/usb/phy c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 35 +tech/debug/hwtracing ee4a490ad48a7236b3f417efda48cc1393d2e0d9 31 +tech/pmic/misc 6fb618c321fd27ccf873f5b4bc6737baee8fd8bb 8 +tech/mem/iommu 44df12a52b9e962122cf7f6253ca1d6d3f2da862 8 +tech/mm/audio/all 88b8f29570c5211e654cec357e6a1282f92737b7 8 +tech/mm/camss c394dfb4b3768df4d41b9b32bf310c307451fa68 32 +tech/mm/drm b480a075f51d506402f8a081a271e5e05896986e 65 +tech/mm/fastrpc e014e351825ea08a7a6ba61f4c005cf1aebcb147 11 +tech/mm/video dc89f72844c066088e5d47e5efa9e32589b2959d 32 +tech/mm/gpu 4433b066ef8096363c84ab1e9fc6f71e465ac95f 6 +tech/net/ath a91544020bd06f83313c1544f2f94d7c19064843 14 +tech/pm/power bb887016f3998f14184b38d1ae3ced78a6d80567 13 +tech/pm/thermal d36b3ee3b5ce84165d974c7141b15c3b6a283691 7 +tech/security/crypto c36112e9987659986a3171f206e4c4a05932fb8b 14 +tech/security/ice beabac03036a596434bb02c3f91b7c9672ea7c15 9 +tech/storage/all d86d915355ae0f4d79ec0223864f41cb1c30ab70 4 +tech/all/dt/qcs6490 d70580362b1b5c9d8db75e08b810c8a9c8358fc3 21 +tech/all/dt/qcs9100 3853a4908bb4a047bb6d096a83ca28de504b56ac 91 +tech/all/dt/qcs8300 e93aa15800b0cebedc8e0d79e5cf39fb32616e48 24 +tech/all/dt/qcs615 1cc303d042350bbb1e4fc4494c33356769995308 8 +tech/all/dt/agatti c828f10cd2c53b7ff2cc061e73b239973ee17bc6 1 +tech/all/dt/hamoa 723e3ef44a909d5e2a4b270d6bccdbeec975b9d1 32 +tech/all/dt/kaanapali f6ed56b503a15dc168700ec4f02e0365680c2cf4 20 +tech/all/dt/pakala b2e5e9630f3ff8f681ae77aaab3ef852c4896df4 12 +tech/all/config 2f8abb9a606bd9d9194983ee7ed3d0a4ee20bca2 69 +tech/overlay/dt cb96f0691662ec18e92c2cbc483351e4ebdf11f5 68 +tech/all/workaround ecc126013f9aac2681125eddbe60f7fa40beeaa3 26 +tech/mproc/all 0aa90b7d45babe6116bcbb3006ae4636256b6e0f 3 +tech/noup/debug/all cbdd4bbfa24a682d76769d4c1c66bb67b262ae4d 26 +tech/hwe/unoq a2d85fe547167dbd8fc59618907c20a6f17d2e5a 4 +early/hwe/shikra/drivers f5654fe87079b83cd2bfc1a4bf10a7bf331ad4dd 160 +early/hwe/shikra/dt e6da759870c85255263830048e5567d47dab3978 122