diff options
Diffstat (limited to 'drivers/soc/qcom')
-rw-r--r-- | drivers/soc/qcom/Kconfig | 8 | ||||
-rw-r--r-- | drivers/soc/qcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/mdt_loader.c | 10 | ||||
-rw-r--r-- | drivers/soc/qcom/qcom-geni-se.c | 13 | ||||
-rw-r--r-- | drivers/soc/qcom/qcom_stats.c | 133 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmh-rsc.c | 7 | ||||
-rw-r--r-- | drivers/soc/qcom/socinfo.c | 13 | ||||
-rw-r--r-- | drivers/soc/qcom/ubwc_config.c | 299 |
8 files changed, 468 insertions, 16 deletions
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 58e63cf0036b..2caadbbcf830 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -296,3 +296,11 @@ config QCOM_PBS PBS trigger event to the PBS RAM. endmenu + +config QCOM_UBWC_CONFIG + tristate + help + Most Qualcomm SoCs feature a number of Universal Bandwidth Compression + (UBWC) engines across various IP blocks, which need to be initialized + with coherent configuration data. This module functions as a single + source of truth for that information. diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index acbca2ab5cc2..b7f1d2a57367 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_QCOM_ICC_BWMON) += icc-bwmon.o qcom_ice-objs += ice.o obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE) += qcom_ice.o obj-$(CONFIG_QCOM_PBS) += qcom-pbs.o +obj-$(CONFIG_QCOM_UBWC_CONFIG) += ubwc_config.o diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 29124aa6d03b..5710ac0c07a8 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -51,7 +51,7 @@ static bool mdt_header_valid(const struct firmware *fw) return true; } -static bool mdt_phdr_valid(const struct elf32_phdr *phdr) +static bool mdt_phdr_loadable(const struct elf32_phdr *phdr) { if (phdr->p_type != PT_LOAD) return false; @@ -124,7 +124,7 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw) for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; - if (!mdt_phdr_valid(phdr)) + if (!mdt_phdr_loadable(phdr)) continue; if (phdr->p_paddr < min_addr) @@ -262,7 +262,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; - if (!mdt_phdr_valid(phdr)) + if (!mdt_phdr_loadable(phdr)) continue; if (phdr->p_flags & QCOM_MDT_RELOCATABLE) @@ -362,7 +362,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; - if (!mdt_phdr_valid(phdr)) + if (!mdt_phdr_loadable(phdr)) continue; if (phdr->p_flags & QCOM_MDT_RELOCATABLE) @@ -389,7 +389,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; - if (!mdt_phdr_valid(phdr)) + if (!mdt_phdr_loadable(phdr)) continue; offset = phdr->p_paddr - mem_reloc; diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 4cb959106efa..3c3b796333a6 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -895,6 +895,7 @@ static int geni_se_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct geni_wrapper *wrapper; + const struct geni_se_desc *desc; int ret; wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL); @@ -906,13 +907,10 @@ static int geni_se_probe(struct platform_device *pdev) if (IS_ERR(wrapper->base)) return PTR_ERR(wrapper->base); - if (!has_acpi_companion(&pdev->dev)) { - const struct geni_se_desc *desc; - int i; + desc = device_get_match_data(&pdev->dev); - desc = device_get_match_data(&pdev->dev); - if (!desc) - return -EINVAL; + if (!has_acpi_companion(&pdev->dev) && desc->num_clks) { + int i; wrapper->num_clks = min_t(unsigned int, desc->num_clks, MAX_CLKS); @@ -953,6 +951,8 @@ static const struct geni_se_desc qup_desc = { .num_clks = ARRAY_SIZE(qup_clks), }; +static const struct geni_se_desc sa8255p_qup_desc = {}; + static const char * const i2c_master_hub_clks[] = { "s-ahb", }; @@ -965,6 +965,7 @@ static const struct geni_se_desc i2c_master_hub_desc = { static const struct of_device_id geni_se_dt_match[] = { { .compatible = "qcom,geni-se-qup", .data = &qup_desc }, { .compatible = "qcom,geni-se-i2c-master-hub", .data = &i2c_master_hub_desc }, + { .compatible = "qcom,sa8255p-geni-se-qup", .data = &sa8255p_qup_desc }, {} }; MODULE_DEVICE_TABLE(of, geni_se_dt_match); diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 5de99cf59b9f..2e380faf9080 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved. */ +#include <linux/bitfield.h> #include <linux/debugfs.h> #include <linux/device.h> #include <linux/io.h> @@ -11,6 +13,7 @@ #include <linux/platform_device.h> #include <linux/seq_file.h> +#include <linux/soc/qcom/qcom_aoss.h> #include <linux/soc/qcom/smem.h> #include <clocksource/arm_arch_timer.h> @@ -24,6 +27,19 @@ #define ACCUMULATED_OFFSET 0x18 #define CLIENT_VOTES_OFFSET 0x20 +#define DDR_STATS_MAGIC_KEY 0xA1157A75 +#define DDR_STATS_MAX_NUM_MODES 20 +#define DDR_STATS_MAGIC_KEY_ADDR 0x0 +#define DDR_STATS_NUM_MODES_ADDR 0x4 +#define DDR_STATS_ENTRY_START_ADDR 0x8 + +#define DDR_STATS_CP_IDX(data) FIELD_GET(GENMASK(4, 0), data) +#define DDR_STATS_LPM_NAME(data) FIELD_GET(GENMASK(7, 0), data) +#define DDR_STATS_TYPE(data) FIELD_GET(GENMASK(15, 8), data) +#define DDR_STATS_FREQ(data) FIELD_GET(GENMASK(31, 16), data) + +static struct qmp *qcom_stats_qmp; + struct subsystem_data { const char *name; u32 smem_item; @@ -48,12 +64,19 @@ static const struct subsystem_data subsystems[] = { struct stats_config { size_t stats_offset; + size_t ddr_stats_offset; size_t num_records; bool appended_stats_avail; bool dynamic_offset; bool subsystem_stats_in_smem; }; +struct ddr_stats_entry { + u32 name; + u32 count; + u64 duration; +}; + struct stats_data { bool appended_stats_avail; void __iomem *base; @@ -122,8 +145,101 @@ static int qcom_soc_sleep_stats_show(struct seq_file *s, void *unused) return 0; } +static void qcom_ddr_stats_print(struct seq_file *s, struct ddr_stats_entry *data) +{ + u32 cp_idx; + + /* + * DDR statistic have two different types of details encoded. + * (1) DDR LPM Stats + * (2) DDR Frequency Stats + * + * The name field have details like which type of DDR stat (bits 8:15) + * along with other details as explained below + * + * In case of DDR LPM stat, name field will be encoded as, + * Bits - Meaning + * 0:7 - DDR LPM name, can be of 0xd4, 0xd3, 0x11 and 0xd0. + * 8:15 - 0x0 (indicates its a LPM stat) + * 16:31 - Unused + * + * In case of DDR FREQ stats, name field will be encoded as, + * Bits - Meaning + * 0:4 - DDR Clock plan index (CP IDX) + * 5:7 - Unused + * 8:15 - 0x1 (indicates its Freq stat) + * 16:31 - Frequency value in Mhz + */ + switch (DDR_STATS_TYPE(data->name)) { + case 0: + seq_printf(s, "DDR LPM Stat Name:0x%lx\tcount:%u\tDuration (ticks):%llu\n", + DDR_STATS_LPM_NAME(data->name), data->count, data->duration); + break; + case 1: + if (!data->count || !DDR_STATS_FREQ(data->name)) + return; + + cp_idx = DDR_STATS_CP_IDX(data->name); + seq_printf(s, "DDR Freq %luMhz:\tCP IDX:%u\tcount:%u\tDuration (ticks):%llu\n", + DDR_STATS_FREQ(data->name), cp_idx, data->count, data->duration); + break; + } +} + +static int qcom_ddr_stats_show(struct seq_file *s, void *d) +{ + struct ddr_stats_entry data[DDR_STATS_MAX_NUM_MODES]; + void __iomem *reg = (void __iomem *)s->private; + u32 entry_count; + int i, ret; + + entry_count = readl_relaxed(reg + DDR_STATS_NUM_MODES_ADDR); + if (entry_count > DDR_STATS_MAX_NUM_MODES) + return -EINVAL; + + if (qcom_stats_qmp) { + /* + * Recent SoCs (SM8450 onwards) do not have duration field + * populated from boot up onwards for both DDR LPM Stats + * and DDR Frequency Stats. + * + * Send QMP message to Always on processor which will + * populate duration field into MSG RAM area. + * + * Sent every time to read latest data. + */ + ret = qmp_send(qcom_stats_qmp, "{class: ddr, action: freqsync}"); + if (ret) + return ret; + } + + reg += DDR_STATS_ENTRY_START_ADDR; + memcpy_fromio(data, reg, sizeof(struct ddr_stats_entry) * entry_count); + + for (i = 0; i < entry_count; i++) + qcom_ddr_stats_print(s, &data[i]); + + return 0; +} + DEFINE_SHOW_ATTRIBUTE(qcom_soc_sleep_stats); DEFINE_SHOW_ATTRIBUTE(qcom_subsystem_sleep_stats); +DEFINE_SHOW_ATTRIBUTE(qcom_ddr_stats); + +static void qcom_create_ddr_stat_files(struct dentry *root, void __iomem *reg, + const struct stats_config *config) +{ + u32 key; + + if (!config->ddr_stats_offset) + return; + + key = readl_relaxed(reg + config->ddr_stats_offset + DDR_STATS_MAGIC_KEY_ADDR); + if (key == DDR_STATS_MAGIC_KEY) + debugfs_create_file("ddr_stats", 0400, root, + (__force void *)reg + config->ddr_stats_offset, + &qcom_ddr_stats_fops); +} static void qcom_create_soc_sleep_stat_files(struct dentry *root, void __iomem *reg, struct stats_data *d, @@ -207,11 +323,27 @@ static int qcom_stats_probe(struct platform_device *pdev) for (i = 0; i < config->num_records; i++) d[i].appended_stats_avail = config->appended_stats_avail; + /* + * QMP is used for DDR stats syncing to MSG RAM for recent SoCs (SM8450 onwards). + * The prior SoCs do not need QMP handle as the required stats are already present + * in MSG RAM, provided the DDR_STATS_MAGIC_KEY matches. + */ + qcom_stats_qmp = qmp_get(&pdev->dev); + if (IS_ERR(qcom_stats_qmp)) { + /* We ignore error if QMP is not defined/needed */ + if (!of_property_present(pdev->dev.of_node, "qcom,qmp")) + qcom_stats_qmp = NULL; + else if (PTR_ERR(qcom_stats_qmp) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else + return PTR_ERR(qcom_stats_qmp); + } root = debugfs_create_dir("qcom_stats", NULL); qcom_create_subsystem_stat_files(root, config); qcom_create_soc_sleep_stat_files(root, reg, d, config); + qcom_create_ddr_stat_files(root, reg, config); platform_set_drvdata(pdev, root); @@ -254,6 +386,7 @@ static const struct stats_config rpmh_data_sdm845 = { static const struct stats_config rpmh_data = { .stats_offset = 0x48, + .ddr_stats_offset = 0xb8, .num_records = 3, .appended_stats_avail = false, .dynamic_offset = false, diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index fdab2b1067db..c6f7d5c9c493 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -453,13 +453,10 @@ static irqreturn_t tcs_tx_done(int irq, void *p) trace_rpmh_tx_done(drv, i, req); - /* - * If wake tcs was re-purposed for sending active - * votes, clear AMC trigger & enable modes and + /* Clear AMC trigger & enable modes and * disable interrupt for this TCS */ - if (!drv->tcs[ACTIVE_TCS].num_tcs) - __tcs_set_trigger(drv, i, false); + __tcs_set_trigger(drv, i, false); skip: /* Reclaim the TCS */ write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i, 0); diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 8c4147737c35..963772f45489 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -38,6 +38,7 @@ #define SMEM_IMAGE_TABLE_BOOT_INDEX 0 #define SMEM_IMAGE_TABLE_TZ_INDEX 1 #define SMEM_IMAGE_TABLE_RPM_INDEX 3 +#define SMEM_IMAGE_TABLE_APPSBL_INDEX 9 #define SMEM_IMAGE_TABLE_APPS_INDEX 10 #define SMEM_IMAGE_TABLE_MPSS_INDEX 11 #define SMEM_IMAGE_TABLE_ADSP_INDEX 12 @@ -48,6 +49,7 @@ #define SMEM_IMAGE_TABLE_CDSP1_INDEX 19 #define SMEM_IMAGE_TABLE_GPDSP_INDEX 20 #define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21 +#define SMEM_IMAGE_TABLE_TME_INDEX 28 #define SMEM_IMAGE_VERSION_TABLE 469 /* @@ -55,6 +57,7 @@ */ static const char *const socinfo_image_names[] = { [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp", + [SMEM_IMAGE_TABLE_APPSBL_INDEX] = "appsbl", [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps", [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot", [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss", @@ -67,6 +70,7 @@ static const char *const socinfo_image_names[] = { [SMEM_IMAGE_TABLE_CDSP1_INDEX] = "cdsp1", [SMEM_IMAGE_TABLE_GPDSP_INDEX] = "gpdsp", [SMEM_IMAGE_TABLE_GPDSP1_INDEX] = "gpdsp1", + [SMEM_IMAGE_TABLE_TME_INDEX] = "tme", }; static const char *const pmic_models[] = { @@ -126,8 +130,12 @@ static const char *const pmic_models[] = { [72] = "PMR735D", [73] = "PM8550", [74] = "PMK8550", + [78] = "PMM8650AU", + [79] = "PMM8650AU_PSAIL", + [80] = "PM7550", [82] = "PMC8380", [83] = "SMB2360", + [91] = "PMIV0108", }; struct socinfo_params { @@ -446,8 +454,13 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QCM8550) }, { qcom_board_id(SM8750) }, { qcom_board_id(IPQ5300) }, + { qcom_board_id(SM7635) }, + { qcom_board_id(SM6650) }, + { qcom_board_id(SM6650P) }, { qcom_board_id(IPQ5321) }, { qcom_board_id(IPQ5424) }, + { qcom_board_id(QCM6690) }, + { qcom_board_id(QCS6690) }, { qcom_board_id(IPQ5404) }, { qcom_board_id(QCS9100) }, { qcom_board_id(QCS8300) }, diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c new file mode 100644 index 000000000000..15d373bff231 --- /dev/null +++ b/drivers/soc/qcom/ubwc_config.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include <linux/debugfs.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include <linux/soc/qcom/ubwc.h> + +static const struct qcom_ubwc_cfg_data no_ubwc_data = { + /* no UBWC, no HBB */ +}; + +static const struct qcom_ubwc_cfg_data msm8937_data = { + .ubwc_enc_version = UBWC_1_0, + .ubwc_dec_version = UBWC_1_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL1 | + UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data msm8998_data = { + .ubwc_enc_version = UBWC_1_0, + .ubwc_dec_version = UBWC_1_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL1 | + UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 15, +}; + +static const struct qcom_ubwc_cfg_data qcm2290_data = { + /* no UBWC */ + .highest_bank_bit = 15, +}; + +static const struct qcom_ubwc_cfg_data sa8775p_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 13, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sar2130p_data = { + .ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */ + .ubwc_dec_version = UBWC_4_3, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 13, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sc7180_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sc7280_data = { + .ubwc_enc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 14, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sc8180x_data = { + .ubwc_enc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_3_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sc8280xp_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sdm670_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sdm845_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 15, +}; + +static const struct qcom_ubwc_cfg_data sm6115_data = { + .ubwc_enc_version = UBWC_1_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL1 | + UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sm6125_data = { + .ubwc_enc_version = UBWC_1_0, + .ubwc_dec_version = UBWC_3_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL1 | + UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sm6150_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sm6350_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sm7150_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 14, +}; + +static const struct qcom_ubwc_cfg_data sm8150_data = { + .ubwc_enc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_3_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .highest_bank_bit = 15, +}; + +static const struct qcom_ubwc_cfg_data sm8250_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 15 for LP_DDR4 */ + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sm8350_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 15 for LP_DDR4 */ + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sm8550_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_3, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 15 for LP_DDR4 */ + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data sm8750_data = { + .ubwc_enc_version = UBWC_5_0, + .ubwc_dec_version = UBWC_5_0, + .ubwc_swizzle = 6, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 15 for LP_DDR4 */ + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct qcom_ubwc_cfg_data x1e80100_data = { + .ubwc_enc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_3, + .ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 | + UBWC_SWIZZLE_ENABLE_LVL3, + .ubwc_bank_spread = true, + /* TODO: highest_bank_bit = 15 for LP_DDR4 */ + .highest_bank_bit = 16, + .macrotile_mode = true, +}; + +static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { + { .compatible = "qcom,apq8016", .data = &no_ubwc_data }, + { .compatible = "qcom,apq8026", .data = &no_ubwc_data }, + { .compatible = "qcom,apq8074", .data = &no_ubwc_data }, + { .compatible = "qcom,apq8096", .data = &msm8998_data }, + { .compatible = "qcom,msm8226", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8916", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8917", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8937", .data = &msm8937_data }, + { .compatible = "qcom,msm8929", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8939", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8953", .data = &msm8937_data }, + { .compatible = "qcom,msm8956", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8974", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8976", .data = &no_ubwc_data }, + { .compatible = "qcom,msm8996", .data = &msm8998_data }, + { .compatible = "qcom,msm8998", .data = &msm8998_data }, + { .compatible = "qcom,qcm2290", .data = &qcm2290_data, }, + { .compatible = "qcom,qcm6490", .data = &sc7280_data, }, + { .compatible = "qcom,sa8155p", .data = &sm8150_data, }, + { .compatible = "qcom,sa8540p", .data = &sc8280xp_data, }, + { .compatible = "qcom,sa8775p", .data = &sa8775p_data, }, + { .compatible = "qcom,sar2130p", .data = &sar2130p_data }, + { .compatible = "qcom,sc7180", .data = &sc7180_data }, + { .compatible = "qcom,sc7280", .data = &sc7280_data, }, + { .compatible = "qcom,sc8180x", .data = &sc8180x_data, }, + { .compatible = "qcom,sc8280xp", .data = &sc8280xp_data, }, + { .compatible = "qcom,sda660", .data = &msm8937_data }, + { .compatible = "qcom,sdm450", .data = &msm8937_data }, + { .compatible = "qcom,sdm630", .data = &msm8937_data }, + { .compatible = "qcom,sdm632", .data = &msm8937_data }, + { .compatible = "qcom,sdm636", .data = &msm8937_data }, + { .compatible = "qcom,sdm660", .data = &msm8937_data }, + { .compatible = "qcom,sdm670", .data = &sdm670_data, }, + { .compatible = "qcom,sdm845", .data = &sdm845_data, }, + { .compatible = "qcom,sm4250", .data = &sm6115_data, }, + { .compatible = "qcom,sm6115", .data = &sm6115_data, }, + { .compatible = "qcom,sm6125", .data = &sm6125_data, }, + { .compatible = "qcom,sm6150", .data = &sm6150_data, }, + { .compatible = "qcom,sm6350", .data = &sm6350_data, }, + { .compatible = "qcom,sm6375", .data = &sm6350_data, }, + { .compatible = "qcom,sm7125", .data = &sc7180_data }, + { .compatible = "qcom,sm7150", .data = &sm7150_data, }, + { .compatible = "qcom,sm7225", .data = &sm6350_data, }, + { .compatible = "qcom,sm7325", .data = &sc7280_data, }, + { .compatible = "qcom,sm8150", .data = &sm8150_data, }, + { .compatible = "qcom,sm8250", .data = &sm8250_data, }, + { .compatible = "qcom,sm8350", .data = &sm8350_data, }, + { .compatible = "qcom,sm8450", .data = &sm8350_data, }, + { .compatible = "qcom,sm8550", .data = &sm8550_data, }, + { .compatible = "qcom,sm8650", .data = &sm8550_data, }, + { .compatible = "qcom,sm8750", .data = &sm8750_data, }, + { .compatible = "qcom,x1e80100", .data = &x1e80100_data, }, + { .compatible = "qcom,x1p42100", .data = &x1e80100_data, }, + { } +}; + +const struct qcom_ubwc_cfg_data *qcom_ubwc_config_get_data(void) +{ + const struct of_device_id *match; + struct device_node *root; + + root = of_find_node_by_path("/"); + if (!root) + return ERR_PTR(-ENODEV); + + match = of_match_node(qcom_ubwc_configs, root); + of_node_put(root); + if (!match) { + pr_err("Couldn't find UBWC config data for this platform!\n"); + return ERR_PTR(-EINVAL); + } + + return match->data; +} +EXPORT_SYMBOL_GPL(qcom_ubwc_config_get_data); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("UBWC config database for QTI SoCs"); |