summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/llcc-qcom.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-04-25 22:02:16 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2023-04-25 22:02:16 +0300
commita907047732470f75f3b7c9a8ee09b16765b8364c (patch)
treec14d8b6220f80f4c87e8dc0eb6d6fa2581e9a294 /drivers/soc/qcom/llcc-qcom.c
parent18032df5ef5c0eec2adf120142bd95a3a8807866 (diff)
parent4c87f3ff78b20da0dd118762fd66b67a98e36249 (diff)
downloadlinux-a907047732470f75f3b7c9a8ee09b16765b8364c.tar.xz
Merge tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann: "The most notable updates this time are for Qualcomm Snapdragon platforms. The Inline-Crypto-Engine gets a new DT binding and driver, and a number of drivers now support additional Snapdragon variants, in particular the rsc, scm, geni, bwm, glink and socinfo, while the llcc (edac) and rpm drivers get notable functionality updates. Updates on other platforms include: - Various updates to the Mediatek mutex and mmsys drivers, including support for the Helio X10 SoC - Support for unidirectional mailbox channels in Arm SCMI firmware - Support for per cpu asynchronous notification in OP-TEE firmware - Minor updates for memory controller drivers. - Minor updates for Renesas, TI, Amlogic, Apple, Broadcom, Tegra, Allwinner, Versatile Express, Canaan, Microchip, Mediatek and i.MX SoC drivers, mainly updating the use of MODULE_LICENSE() macros and obsolete DT driver interfaces" * tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (165 commits) soc: ti: smartreflex: Simplify getting the opam_sr pointer bus: vexpress-config: Add explicit of_platform.h include soc: mediatek: Kconfig: Add MTK_CMDQ dependency to MTK_MMSYS memory: mtk-smi: mt8365: Add SMI Support dt-bindings: memory-controllers: mediatek,smi-larb: add mt8365 dt-bindings: memory-controllers: mediatek,smi-common: add mt8365 memory: tegra: read values from correct device dt-bindings: crypto: Add Qualcomm Inline Crypto Engine soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver dt-bindings: firmware: document Qualcomm QCM2290 SCM soc: qcom: rpmh-rsc: Support RSC v3 minor versions soc: qcom: smd-rpm: Use GFP_ATOMIC in write path soc/tegra: fuse: Remove nvmem root only access soc/tegra: cbb: tegra194: Use of_address_count() helper soc/tegra: cbb: Remove MODULE_LICENSE in non-modules ARM: tegra: Remove MODULE_LICENSE in non-modules soc/tegra: flowctrl: Use devm_platform_get_and_ioremap_resource() soc: tegra: cbb: Drop empty platform remove function firmware: arm_scmi: Add support for unidirectional mailbox channels dt-bindings: firmware: arm,scmi: Support mailboxes unidirectional channels ...
Diffstat (limited to 'drivers/soc/qcom/llcc-qcom.c')
-rw-r--r--drivers/soc/qcom/llcc-qcom.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 26efe12012a0..67c19ed2219a 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -62,8 +62,6 @@
#define LLCC_TRP_WRSC_CACHEABLE_EN 0x21f2c
#define LLCC_TRP_ALGO_CFG8 0x21f30
-#define BANK_OFFSET_STRIDE 0x80000
-
#define LLCC_VERSION_2_0_0_0 0x02000000
#define LLCC_VERSION_2_1_0_0 0x02010000
#define LLCC_VERSION_4_1_0_0 0x04010000
@@ -122,10 +120,11 @@ struct llcc_slice_config {
struct qcom_llcc_config {
const struct llcc_slice_config *sct_data;
- int size;
- bool need_llcc_cfg;
const u32 *reg_offset;
const struct llcc_edac_reg_offset *edac_reg_offset;
+ int size;
+ bool need_llcc_cfg;
+ bool no_edac;
};
enum llcc_reg_offset {
@@ -227,6 +226,14 @@ static const struct llcc_slice_config sm6350_data[] = {
{ LLCC_MODPE, 29, 64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
};
+static const struct llcc_slice_config sm7150_data[] = {
+ { LLCC_CPUSS, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1 },
+ { LLCC_MDM, 8, 128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+ { LLCC_GPUHTW, 11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+ { LLCC_GPU, 12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+ { LLCC_NPU, 23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+};
+
static const struct llcc_slice_config sm8150_data[] = {
{ LLCC_CPUSS, 1, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 1 },
{ LLCC_VIDSC0, 2, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
@@ -454,6 +461,7 @@ static const struct qcom_llcc_config sdm845_cfg = {
.need_llcc_cfg = false,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
+ .no_edac = true,
};
static const struct qcom_llcc_config sm6350_cfg = {
@@ -464,6 +472,14 @@ static const struct qcom_llcc_config sm6350_cfg = {
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
+static const struct qcom_llcc_config sm7150_cfg = {
+ .sct_data = sm7150_data,
+ .size = ARRAY_SIZE(sm7150_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+};
+
static const struct qcom_llcc_config sm8150_cfg = {
.sct_data = sm8150_data,
.size = ARRAY_SIZE(sm8150_data),
@@ -898,8 +914,8 @@ static int qcom_llcc_remove(struct platform_device *pdev)
return 0;
}
-static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
- const char *name)
+static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, u8 index,
+ const char *name)
{
void __iomem *base;
struct regmap_config llcc_regmap_config = {
@@ -909,7 +925,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
.fast_io = true,
};
- base = devm_platform_ioremap_resource_byname(pdev, name);
+ base = devm_platform_ioremap_resource(pdev, index);
if (IS_ERR(base))
return ERR_CAST(base);
@@ -927,6 +943,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
const struct llcc_slice_config *llcc_cfg;
u32 sz;
u32 version;
+ struct regmap *regmap;
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
if (!drv_data) {
@@ -934,21 +951,51 @@ static int qcom_llcc_probe(struct platform_device *pdev)
goto err;
}
- drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
- if (IS_ERR(drv_data->regmap)) {
- ret = PTR_ERR(drv_data->regmap);
+ /* Initialize the first LLCC bank regmap */
+ regmap = qcom_llcc_init_mmio(pdev, 0, "llcc0_base");
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto err;
+ }
+
+ cfg = of_device_get_match_data(&pdev->dev);
+
+ ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks);
+ if (ret)
+ goto err;
+
+ num_banks &= LLCC_LB_CNT_MASK;
+ num_banks >>= LLCC_LB_CNT_SHIFT;
+ drv_data->num_banks = num_banks;
+
+ drv_data->regmaps = devm_kcalloc(dev, num_banks, sizeof(*drv_data->regmaps), GFP_KERNEL);
+ if (!drv_data->regmaps) {
+ ret = -ENOMEM;
goto err;
}
- drv_data->bcast_regmap =
- qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
+ drv_data->regmaps[0] = regmap;
+
+ /* Initialize rest of LLCC bank regmaps */
+ for (i = 1; i < num_banks; i++) {
+ char *base = kasprintf(GFP_KERNEL, "llcc%d_base", i);
+
+ drv_data->regmaps[i] = qcom_llcc_init_mmio(pdev, i, base);
+ if (IS_ERR(drv_data->regmaps[i])) {
+ ret = PTR_ERR(drv_data->regmaps[i]);
+ kfree(base);
+ goto err;
+ }
+
+ kfree(base);
+ }
+
+ drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
if (IS_ERR(drv_data->bcast_regmap)) {
ret = PTR_ERR(drv_data->bcast_regmap);
goto err;
}
- cfg = of_device_get_match_data(&pdev->dev);
-
/* Extract version of the IP */
ret = regmap_read(drv_data->bcast_regmap, cfg->reg_offset[LLCC_COMMON_HW_INFO],
&version);
@@ -957,15 +1004,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->version = version;
- ret = regmap_read(drv_data->regmap, cfg->reg_offset[LLCC_COMMON_STATUS0],
- &num_banks);
- if (ret)
- goto err;
-
- num_banks &= LLCC_LB_CNT_MASK;
- num_banks >>= LLCC_LB_CNT_SHIFT;
- drv_data->num_banks = num_banks;
-
llcc_cfg = cfg->sct_data;
sz = cfg->size;
@@ -973,16 +1011,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
if (llcc_cfg[i].slice_id > drv_data->max_slices)
drv_data->max_slices = llcc_cfg[i].slice_id;
- drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
- GFP_KERNEL);
- if (!drv_data->offsets) {
- ret = -ENOMEM;
- goto err;
- }
-
- for (i = 0; i < num_banks; i++)
- drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
-
drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices,
GFP_KERNEL);
if (!drv_data->bitmap) {
@@ -1001,7 +1029,14 @@ static int qcom_llcc_probe(struct platform_device *pdev)
goto err;
drv_data->ecc_irq = platform_get_irq_optional(pdev, 0);
- if (drv_data->ecc_irq >= 0) {
+
+ /*
+ * On some platforms, the access to EDAC registers will be locked by
+ * the bootloader. So probing the EDAC driver will result in a crash.
+ * Hence, disable the creation of EDAC platform device for the
+ * problematic platforms.
+ */
+ if (!cfg->no_edac) {
llcc_edac = platform_device_register_data(&pdev->dev,
"qcom_llcc_edac", -1, drv_data,
sizeof(*drv_data));
@@ -1022,6 +1057,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfg },
{ .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
{ .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg },
+ { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfg },
{ .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
{ .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
{ .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg },