From 960ddf70cc11024e6e9dac206316d0160e00a77d Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 11 Dec 2020 13:58:46 +0000 Subject: drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs Since at91_soc_init is called unconditionally from atmel_soc_device_init, we get the following warning on all non AT91 SoCs: " AT91: Could not find identification node" Fix the same by filtering with allowed AT91 SoC list. Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Ludovic Desroches Signed-off-by: Sudeep Holla Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20201211135846.1334322-1-sudeep.holla@arm.com --- drivers/soc/atmel/soc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index c4472b68b7c2..728d461ad6d6 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -271,8 +271,20 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) return soc_dev; } +static const struct of_device_id at91_soc_allowed_list[] __initconst = { + { .compatible = "atmel,at91rm9200", }, + { .compatible = "atmel,at91sam9", }, + { .compatible = "atmel,sama5", }, + { .compatible = "atmel,samv7", } +}; + static int __init atmel_soc_device_init(void) { + struct device_node *np = of_find_node_by_path("/"); + + if (!of_match_node(at91_soc_allowed_list, np)) + return 0; + at91_soc_init(socs); return 0; -- cgit v1.2.3 From f426c3b1d66fb76ad11ef097e840c0eb32b7f9be Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Mon, 30 Nov 2020 15:09:21 +0530 Subject: dt-bindings: msm: Add LLCC for SM8250 Add LLCC compatible for SM8250 SoC. Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20201130093924.45057-2-manivannan.sadhasivam@linaro.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml index 0a9889debc7c..c299dc907f6c 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml @@ -24,6 +24,7 @@ properties: - qcom,sc7180-llcc - qcom,sdm845-llcc - qcom,sm8150-llcc + - qcom,sm8250-llcc reg: items: -- cgit v1.2.3 From 916c0c05521a52f13283ad3600793fc79516ff31 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Mon, 30 Nov 2020 15:09:23 +0530 Subject: soc: qcom: llcc-qcom: Extract major hardware version The major hardware version of the LLCC IP is encoded in its LLCC_COMMON_HW_INFO register. Extract the version and cache it in the driver data so that it can be used to implement version specific functionality like enabling Write sub cache for given SCID. Signed-off-by: Sai Prakash Ranjan [mani: splitted the version extract as a single patch and few cleanups] Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20201130093924.45057-4-manivannan.sadhasivam@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 12 ++++++++++++ include/linux/soc/qcom/llcc-qcom.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 16b421608e9c..a559617ea7c0 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4,6 +4,7 @@ * */ +#include #include #include #include @@ -35,6 +36,9 @@ #define CACHE_LINE_SIZE_SHIFT 6 +#define LLCC_COMMON_HW_INFO 0x00030000 +#define LLCC_MAJOR_VERSION_MASK GENMASK(31, 24) + #define LLCC_COMMON_STATUS0 0x0003000c #define LLCC_LB_CNT_MASK GENMASK(31, 28) #define LLCC_LB_CNT_SHIFT 28 @@ -476,6 +480,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) const struct qcom_llcc_config *cfg; const struct llcc_slice_config *llcc_cfg; u32 sz; + u32 version; drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); if (!drv_data) { @@ -496,6 +501,13 @@ static int qcom_llcc_probe(struct platform_device *pdev) goto err; } + /* Extract major version of the IP */ + ret = regmap_read(drv_data->bcast_regmap, LLCC_COMMON_HW_INFO, &version); + if (ret) + goto err; + + drv_data->major_version = FIELD_GET(LLCC_MAJOR_VERSION_MASK, version); + ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, &num_banks); if (ret) diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 3db6797ba6ff..d17a3de80510 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -79,6 +79,7 @@ struct llcc_edac_reg_data { * @bitmap: Bit map to track the active slice ids * @offsets: Pointer to the bank offsets array * @ecc_irq: interrupt for llcc cache error detection and reporting + * @major_version: Indicates the LLCC major version */ struct llcc_drv_data { struct regmap *regmap; @@ -91,6 +92,7 @@ struct llcc_drv_data { unsigned long *bitmap; u32 *offsets; int ecc_irq; + u32 major_version; }; #if IS_ENABLED(CONFIG_QCOM_LLCC) -- cgit v1.2.3 From c4df37fe186de4df8895a7a4793f5221eda6e5ae Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Mon, 30 Nov 2020 15:09:24 +0530 Subject: soc: qcom: llcc-qcom: Add support for SM8250 SoC SM8250 SoC uses LLCC IP version 2. In this version, the WRSC_EN register needs to be written to enable the Write Sub Cache for each SCID. Hence, use a dedicated "write_scid_en" member with predefined values and write them for LLCC IP version 2. Reviewed-by: Sai Prakash Ranjan Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20201130093924.45057-5-manivannan.sadhasivam@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/soc/qcom/llcc-qcom.h | 1 + 2 files changed, 39 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index a559617ea7c0..8403a77b59fe 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -51,6 +51,7 @@ #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 +#define LLCC_TRP_WRSC_EN 0x21f20 #define BANK_OFFSET_STRIDE 0x80000 @@ -77,6 +78,7 @@ * then the ways assigned to this client are not flushed on power * collapse. * @activate_on_init: Activate the slice immediately after it is programmed + * @write_scid_en: Bit enables write cache support for a given scid. */ struct llcc_slice_config { u32 usecase_id; @@ -91,6 +93,7 @@ struct llcc_slice_config { bool dis_cap_alloc; bool retain_on_pc; bool activate_on_init; + bool write_scid_en; }; struct qcom_llcc_config { @@ -151,6 +154,25 @@ static const struct llcc_slice_config sm8150_data[] = { { LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 }, }; +static const struct llcc_slice_config sm8250_data[] = { + { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 }, + { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, + { LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, + { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 }, + { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_VIDFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 }, + { LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, +}; + static const struct qcom_llcc_config sc7180_cfg = { .sct_data = sc7180_data, .size = ARRAY_SIZE(sc7180_data), @@ -168,6 +190,11 @@ static const struct qcom_llcc_config sm8150_cfg = { .size = ARRAY_SIZE(sm8150_data), }; +static const struct qcom_llcc_config sm8250_cfg = { + .sct_data = sm8250_data, + .size = ARRAY_SIZE(sm8250_data), +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -417,6 +444,16 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } + if (drv_data->major_version == 2) { + u32 wren; + + wren = config->write_scid_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_EN, + BIT(config->slice_id), wren); + if (ret) + return ret; + } + if (config->activate_on_init) { desc.slice_id = config->slice_id; ret = llcc_slice_activate(&desc); @@ -571,6 +608,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg }, { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg }, + { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, { } }; diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index d17a3de80510..64fc582ae415 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -29,6 +29,7 @@ #define LLCC_AUDHW 22 #define LLCC_NPU 23 #define LLCC_WLHW 24 +#define LLCC_CVP 28 #define LLCC_MODPE 29 #define LLCC_APTCM 30 #define LLCC_WRCACHE 31 -- cgit v1.2.3 From e1d8008179fef782ecea4e7af1b9cd9891bd881e Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Tue, 24 Nov 2020 15:23:30 +0530 Subject: drivers: qcom: rpmh-rsc: Do not read back the register write on trigger When triggering a TCS to send its contents, reading back the trigger value may return an incorrect value. That is because, writing the trigger may raise an interrupt which could be handled immediately and the trigger value could be reset in the interrupt handler. A write_tcs_reg_sync() would read back the value that is written and try to match it to the value written to ensure that the value is written, but if that value is different, we may see false error for same. Reviewed-by: Douglas Anderson Signed-off-by: Lina Iyer Signed-off-by: Maulik Shah Link: https://lore.kernel.org/r/1606211610-15168-1-git-send-email-mkshah@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 37969dcbaf14..0b082ec894a1 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -364,7 +364,7 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) enable = TCS_AMC_MODE_ENABLE; write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); enable |= TCS_AMC_MODE_TRIGGER; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, enable); } } -- cgit v1.2.3 From e2b0330c5a20baa4ab55553c60412c367d179e7b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 15 Dec 2020 13:45:37 +0300 Subject: dt-bindings: soc: qcom: convert qcom,smem bindings to yaml Convert soc/qcom/qcom,smem.txt bindings to YAML format. Reviewed-by: Bjorn Andersson Reviewed-by: Rob Herring Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201215104537.768914-1-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/soc/qcom/qcom,smem.txt | 57 ----------------- .../devicetree/bindings/soc/qcom/qcom,smem.yaml | 72 ++++++++++++++++++++++ 2 files changed, 72 insertions(+), 57 deletions(-) delete mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt deleted file mode 100644 index 9326cdf6e1b1..000000000000 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt +++ /dev/null @@ -1,57 +0,0 @@ -Qualcomm Shared Memory Manager binding - -This binding describes the Qualcomm Shared Memory Manager, used to share data -between various subsystems and OSes in Qualcomm platforms. - -- compatible: - Usage: required - Value type: - Definition: must be: - "qcom,smem" - -- memory-region: - Usage: required - Value type: - Definition: handle to memory reservation for main SMEM memory region. - -- qcom,rpm-msg-ram: - Usage: required - Value type: - Definition: handle to RPM message memory resource - -- hwlocks: - Usage: required - Value type: - Definition: reference to a hwspinlock used to protect allocations from - the shared memory - -= EXAMPLE -The following example shows the SMEM setup for MSM8974, with a main SMEM region -at 0xfa00000 and the RPM message ram at 0xfc428000: - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - smem_region: smem@fa00000 { - reg = <0xfa00000 0x200000>; - no-map; - }; - }; - - smem@fa00000 { - compatible = "qcom,smem"; - - memory-region = <&smem_region>; - qcom,rpm-msg-ram = <&rpm_msg_ram>; - - hwlocks = <&tcsr_mutex 3>; - }; - - soc { - rpm_msg_ram: memory@fc428000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0xfc428000 0x4000>; - }; - }; diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml new file mode 100644 index 000000000000..f7e17713b3d8 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/soc/qcom/qcom,smem.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Qualcomm Shared Memory Manager binding + +maintainers: + - Andy Gross + - Bjorn Andersson + +description: | + This binding describes the Qualcomm Shared Memory Manager, used to share data + between various subsystems and OSes in Qualcomm platforms. + +properties: + compatible: + const: qcom,smem + + memory-region: + maxItems: 1 + description: handle to memory reservation for main SMEM memory region. + + hwlocks: + maxItems: 1 + + qcom,rpm-msg-ram: + $ref: /schemas/types.yaml#/definitions/phandle + description: handle to RPM message memory resource + +required: + - compatible + - memory-region + - hwlocks + +additionalProperties: false + +examples: + - | + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + smem_region: smem@fa00000 { + reg = <0xfa00000 0x200000>; + no-map; + }; + }; + + smem { + compatible = "qcom,smem"; + + memory-region = <&smem_region>; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + + hwlocks = <&tcsr_mutex 3>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + rpm_msg_ram: sram@fc428000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0xfc428000 0x4000>; + }; + }; + +... -- cgit v1.2.3 From 1b3df368914b5e1783a9192b32418b24b7a721e5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Jul 2020 18:32:20 +0300 Subject: soc: qcom: smem: use %*ph to print small buffer Use %*ph format to print small buffer as hex string. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200730153220.39466-1-andriy.shevchenko@linux.intel.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 7251827bac88..cc4e0655a47b 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -732,9 +732,7 @@ qcom_smem_partition_header(struct qcom_smem *smem, header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { - dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n", - header->magic[0], header->magic[1], - header->magic[2], header->magic[3]); + dev_err(smem->dev, "bad partition magic %4ph\n", header->magic); return NULL; } -- cgit v1.2.3 From a2d522ff0f5cc26915c4ccee9457fd4b4e1edc48 Mon Sep 17 00:00:00 2001 From: Zhang Qilong Date: Mon, 23 Nov 2020 18:21:18 +0800 Subject: memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. We fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced. Fixes: 4f0a1a1ae3519 ("memory: mtk-smi: Invoke pm runtime_callback to enable clocks") Signed-off-by: Zhang Qilong Link: https://lore.kernel.org/r/20201123102118.3866195-1-zhangqilong3@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index ac350f8d1e20..82d09b88240e 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -130,7 +130,7 @@ static void mtk_smi_clk_disable(const struct mtk_smi *smi) int mtk_smi_larb_get(struct device *larbdev) { - int ret = pm_runtime_get_sync(larbdev); + int ret = pm_runtime_resume_and_get(larbdev); return (ret < 0) ? ret : 0; } @@ -374,7 +374,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) int ret; /* Power on smi-common. */ - ret = pm_runtime_get_sync(larb->smi_common_dev); + ret = pm_runtime_resume_and_get(larb->smi_common_dev); if (ret < 0) { dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret); return ret; -- cgit v1.2.3 From bd96a89ca3fe874c98fe057cccb087603d76e5d4 Mon Sep 17 00:00:00 2001 From: Zheng Yongjun Date: Mon, 28 Dec 2020 21:50:56 +0800 Subject: memory: emif: Use DEFINE_SPINLOCK() for spinlock Spinlock can be initialized automatically with DEFINE_SPINLOCK() rather than explicitly calling spin_lock_init(). Signed-off-by: Zheng Yongjun Link: https://lore.kernel.org/r/20201228135056.28511-1-zhengyongjun3@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index ddb1879f07d3..f7825eef5894 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -70,7 +70,7 @@ struct emif_data { }; static struct emif_data *emif1; -static spinlock_t emif_lock; +static DEFINE_SPINLOCK(emif_lock); static unsigned long irq_state; static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); @@ -1531,7 +1531,6 @@ static int __init_or_module emif_probe(struct platform_device *pdev) /* One-time actions taken on probing the first device */ if (!emif1) { emif1 = emif; - spin_lock_init(&emif_lock); /* * TODO: register notifiers for frequency and voltage -- cgit v1.2.3 From 281462e593483350d8072a118c6e072c550a80fa Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 28 Dec 2020 18:49:16 +0300 Subject: memory: tegra124-emc: Make driver modular Add modularization support to the Tegra124 EMC driver, which now can be compiled as a loadable kernel module. Note that EMC clock must be registered at clk-init time, otherwise PLLM will be disabled as unused clock at boot time if EMC driver is compiled as a module. Hence add a prepare/complete callbacks. similarly to what is done for the Tegra20/30 EMC drivers. Tested-by: Nicolas Chauvet Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20201228154920.18846-2-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/clk/tegra/Kconfig | 3 +++ drivers/clk/tegra/Makefile | 2 +- drivers/clk/tegra/clk-tegra124-emc.c | 41 +++++++++++++++++++++++++++++++----- drivers/clk/tegra/clk-tegra124.c | 26 ++++++++++++++++++++--- drivers/clk/tegra/clk.h | 18 ++++++++++------ drivers/memory/tegra/Kconfig | 3 ++- drivers/memory/tegra/tegra124-emc.c | 31 ++++++++++++++++++--------- include/linux/clk/tegra.h | 8 +++++++ include/soc/tegra/emc.h | 16 -------------- 9 files changed, 106 insertions(+), 42 deletions(-) delete mode 100644 include/soc/tegra/emc.h diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig index deaa4605824c..90df619dc087 100644 --- a/drivers/clk/tegra/Kconfig +++ b/drivers/clk/tegra/Kconfig @@ -7,3 +7,6 @@ config TEGRA_CLK_DFLL depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC select PM_OPP def_bool y + +config TEGRA124_CLK_EMC + bool diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index eec2313fd37e..7b1816856eb5 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra20-emc.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o -obj-$(CONFIG_TEGRA124_EMC) += clk-tegra124-emc.o +obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o obj-y += cvb.o obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index 745f9faa98d8..bdf6f4a51617 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -21,7 +23,6 @@ #include #include -#include #include "clk.h" @@ -80,6 +81,9 @@ struct tegra_clk_emc { int num_timings; struct emc_timing *timings; spinlock_t *lock; + + tegra124_emc_prepare_timing_change_cb *prepare_timing_change; + tegra124_emc_complete_timing_change_cb *complete_timing_change; }; /* Common clock framework callback implementations */ @@ -176,6 +180,9 @@ static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra) if (tegra->emc) return tegra->emc; + if (!tegra->prepare_timing_change || !tegra->complete_timing_change) + return NULL; + if (!tegra->emc_node) return NULL; @@ -241,7 +248,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, div = timing->parent_rate / (timing->rate / 2) - 2; - err = tegra_emc_prepare_timing_change(emc, timing->rate); + err = tegra->prepare_timing_change(emc, timing->rate); if (err) return err; @@ -259,7 +266,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, spin_unlock_irqrestore(tegra->lock, flags); - tegra_emc_complete_timing_change(emc, timing->rate); + tegra->complete_timing_change(emc, timing->rate); clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent)); clk_disable_unprepare(tegra->prev_parent); @@ -473,8 +480,8 @@ static const struct clk_ops tegra_clk_emc_ops = { .get_parent = emc_get_parent, }; -struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, - spinlock_t *lock) +struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np, + spinlock_t *lock) { struct tegra_clk_emc *tegra; struct clk_init_data init; @@ -538,3 +545,27 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, return clk; }; + +void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, + tegra124_emc_complete_timing_change_cb *complete_cb) +{ + struct clk *clk = __clk_lookup("emc"); + struct tegra_clk_emc *tegra; + struct clk_hw *hw; + + if (clk) { + hw = __clk_get_hw(clk); + tegra = container_of(hw, struct tegra_clk_emc, hw); + + tegra->prepare_timing_change = prep_cb; + tegra->complete_timing_change = complete_cb; + } +} +EXPORT_SYMBOL_GPL(tegra124_clk_set_emc_callbacks); + +bool tegra124_clk_emc_driver_available(struct clk_hw *hw) +{ + struct tegra_clk_emc *tegra = container_of(hw, struct tegra_clk_emc, hw); + + return tegra->prepare_timing_change && tegra->complete_timing_change; +} diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index e931319dcc9d..934520aab6e3 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1500,6 +1500,26 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np) writel(plld_base, clk_base + PLLD_BASE); } +static struct clk *tegra124_clk_src_onecell_get(struct of_phandle_args *clkspec, + void *data) +{ + struct clk_hw *hw; + struct clk *clk; + + clk = of_clk_src_onecell_get(clkspec, data); + if (IS_ERR(clk)) + return clk; + + hw = __clk_get_hw(clk); + + if (clkspec->args[0] == TEGRA124_CLK_EMC) { + if (!tegra124_clk_emc_driver_available(hw)) + return ERR_PTR(-EPROBE_DEFER); + } + + return clk; +} + /** * tegra124_132_clock_init_post - clock initialization postamble for T124/T132 * @np: struct device_node * of the DT node for the SoC CAR IP block @@ -1516,10 +1536,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np) &pll_x_params); tegra_init_special_resets(1, tegra124_reset_assert, tegra124_reset_deassert); - tegra_add_of_provider(np, of_clk_src_onecell_get); + tegra_add_of_provider(np, tegra124_clk_src_onecell_get); - clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np, - &emc_lock); + clks[TEGRA124_CLK_EMC] = tegra124_clk_register_emc(clk_base, np, + &emc_lock); tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 6b565f6b5f66..c3e36b5dcc75 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -881,16 +881,22 @@ void tegra_super_clk_gen5_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *pll_params); -#ifdef CONFIG_TEGRA124_EMC -struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, - spinlock_t *lock); +#ifdef CONFIG_TEGRA124_CLK_EMC +struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np, + spinlock_t *lock); +bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw); #else -static inline struct clk *tegra_clk_register_emc(void __iomem *base, - struct device_node *np, - spinlock_t *lock) +static inline struct clk * +tegra124_clk_register_emc(void __iomem *base, struct device_node *np, + spinlock_t *lock) { return NULL; } + +static inline bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw) +{ + return false; +} #endif void tegra114_clock_tune_cpu_trimmers_high(void); diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig index ca7077a06f4c..f5b451403c58 100644 --- a/drivers/memory/tegra/Kconfig +++ b/drivers/memory/tegra/Kconfig @@ -32,9 +32,10 @@ config TEGRA30_EMC external memory. config TEGRA124_EMC - bool "NVIDIA Tegra124 External Memory Controller driver" + tristate "NVIDIA Tegra124 External Memory Controller driver" default y depends on TEGRA_MC && ARCH_TEGRA_124_SOC + select TEGRA124_CLK_EMC help This driver is for the External Memory Controller (EMC) found on Tegra124 chips. The EMC controls the external DRAM on the board. diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index ee8ee39e98ed..edfbf6d6d357 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -9,16 +9,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -562,8 +563,8 @@ static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc, return timing; } -int tegra_emc_prepare_timing_change(struct tegra_emc *emc, - unsigned long rate) +static int tegra_emc_prepare_timing_change(struct tegra_emc *emc, + unsigned long rate) { struct emc_timing *timing = tegra_emc_find_timing(emc, rate); struct emc_timing *last = &emc->last_timing; @@ -790,8 +791,8 @@ int tegra_emc_prepare_timing_change(struct tegra_emc *emc, return 0; } -void tegra_emc_complete_timing_change(struct tegra_emc *emc, - unsigned long rate) +static void tegra_emc_complete_timing_change(struct tegra_emc *emc, + unsigned long rate) { struct emc_timing *timing = tegra_emc_find_timing(emc, rate); struct emc_timing *last = &emc->last_timing; @@ -987,6 +988,7 @@ static const struct of_device_id tegra_emc_of_match[] = { { .compatible = "nvidia,tegra132-emc" }, {} }; +MODULE_DEVICE_TABLE(of, tegra_emc_of_match); static struct device_node * tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code) @@ -1226,9 +1228,19 @@ static int tegra_emc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, emc); + tegra124_clk_set_emc_callbacks(tegra_emc_prepare_timing_change, + tegra_emc_complete_timing_change); + if (IS_ENABLED(CONFIG_DEBUG_FS)) emc_debugfs_init(&pdev->dev, emc); + /* + * Don't allow the kernel module to be unloaded. Unloading adds some + * extra complexity which doesn't really worth the effort in a case of + * this driver. + */ + try_module_get(THIS_MODULE); + return 0; }; @@ -1240,9 +1252,8 @@ static struct platform_driver tegra_emc_driver = { .suppress_bind_attrs = true, }, }; +module_platform_driver(tegra_emc_driver); -static int tegra_emc_init(void) -{ - return platform_driver_register(&tegra_emc_driver); -} -subsys_initcall(tegra_emc_init); +MODULE_AUTHOR("Mikko Perttunen "); +MODULE_DESCRIPTION("NVIDIA Tegra124 EMC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index 3f01d43f0598..eb016fc9cc0b 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -136,6 +136,7 @@ extern void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value); extern void tegra210_clk_emc_update_setting(u32 emc_src_value); struct clk; +struct tegra_emc; typedef long (tegra20_clk_emc_round_cb)(unsigned long rate, unsigned long min_rate, @@ -146,6 +147,13 @@ void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, void *cb_arg); int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same); +typedef int (tegra124_emc_prepare_timing_change_cb)(struct tegra_emc *emc, + unsigned long rate); +typedef void (tegra124_emc_complete_timing_change_cb)(struct tegra_emc *emc, + unsigned long rate); +void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, + tegra124_emc_complete_timing_change_cb *complete_cb); + struct tegra210_clk_emc_config { unsigned long rate; bool same_freq; diff --git a/include/soc/tegra/emc.h b/include/soc/tegra/emc.h deleted file mode 100644 index 05199a97ccf4..000000000000 --- a/include/soc/tegra/emc.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2014 NVIDIA Corporation. All rights reserved. - */ - -#ifndef __SOC_TEGRA_EMC_H__ -#define __SOC_TEGRA_EMC_H__ - -struct tegra_emc; - -int tegra_emc_prepare_timing_change(struct tegra_emc *emc, - unsigned long rate); -void tegra_emc_complete_timing_change(struct tegra_emc *emc, - unsigned long rate); - -#endif /* __SOC_TEGRA_EMC_H__ */ -- cgit v1.2.3 From 9c56679d6f67108114ecc1d8db5af8fe2209e923 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 28 Dec 2020 18:49:17 +0300 Subject: memory: tegra124-emc: Continue probing if timings are missing in device-tree EMC driver will become mandatory after turning it into interconnect provider because interconnect users, like display controller driver, will fail to probe using newer device-trees that have interconnect properties. Thus make EMC driver to probe even if timings are missing in device-tree. Tested-by: Nicolas Chauvet Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20201228154920.18846-3-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124-emc.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index edfbf6d6d357..8fb8c1af25c9 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1201,23 +1201,15 @@ static int tegra_emc_probe(struct platform_device *pdev) ram_code = tegra_read_ram_code(); np = tegra_emc_find_node_by_ram_code(pdev->dev.of_node, ram_code); - if (!np) { - dev_err(&pdev->dev, - "no memory timings for RAM code %u found in DT\n", - ram_code); - return -ENOENT; - } - - err = tegra_emc_load_timings_from_dt(emc, np); - of_node_put(np); - if (err) - return err; - - if (emc->num_timings == 0) { - dev_err(&pdev->dev, - "no memory timings for RAM code %u registered\n", - ram_code); - return -ENOENT; + if (np) { + err = tegra_emc_load_timings_from_dt(emc, np); + of_node_put(np); + if (err) + return err; + } else { + dev_info(&pdev->dev, + "no memory timings for RAM code %u found in DT\n", + ram_code); } err = emc_init(emc); -- cgit v1.2.3 From 99a064fb3a73920262119efead4d5048b7da2f55 Mon Sep 17 00:00:00 2001 From: Jim Quinlan Date: Tue, 22 Dec 2020 09:56:02 -0500 Subject: dt-bindings: arm: Add optional interrupt to smc/hvc SCMI transport In the normal use of smc/hvc as SCMI transport, the message completion is indicated by the return of the SMC call. This binding provides for an optional interrupt named "a2p" which can be used instead to indicate the completion of a message. Link: https://lore.kernel.org/r/20201222145603.40192-2-jim2101024@gmail.com Reviewed-by: Rob Herring Acked-by: Florian Fainelli Signed-off-by: Jim Quinlan [sudeep.holla: minor wording changes to the commit log] Signed-off-by: Sudeep Holla --- Documentation/devicetree/bindings/arm/arm,scmi.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt index b5ce5b39bb9c..667d58e0a659 100644 --- a/Documentation/devicetree/bindings/arm/arm,scmi.txt +++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt @@ -31,6 +31,14 @@ Optional properties: - mbox-names: shall be "tx" or "rx" depending on mboxes entries. +- interrupts : when using smc or hvc transports, this optional + property indicates that msg completion by the platform is indicated + by an interrupt rather than by the return of the smc call. This + should not be used except when the platform requires such behavior. + +- interrupt-names : if "interrupts" is present, interrupt-names must also + be present and have the value "a2p". + See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details about the generic mailbox controller and client driver bindings. -- cgit v1.2.3 From 380def2d4cf257663de42618e57134afeded32dd Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 28 Dec 2020 18:49:18 +0300 Subject: memory: tegra124: Support interconnect framework Now Internal and External memory controllers are memory interconnection providers. This allows us to use interconnect API for tuning of memory configuration. EMC driver now supports OPPs and DVFS. Tested-by: Nicolas Chauvet Acked-by: Georgi Djakov Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20201228154920.18846-4-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/Kconfig | 1 + drivers/memory/tegra/tegra124-emc.c | 320 ++++++++++++++++++++++++++++++++++-- drivers/memory/tegra/tegra124.c | 82 ++++++++- 3 files changed, 391 insertions(+), 12 deletions(-) diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig index f5b451403c58..a70967a56e52 100644 --- a/drivers/memory/tegra/Kconfig +++ b/drivers/memory/tegra/Kconfig @@ -36,6 +36,7 @@ config TEGRA124_EMC default y depends on TEGRA_MC && ARCH_TEGRA_124_SOC select TEGRA124_CLK_EMC + select PM_OPP help This driver is for the External Memory Controller (EMC) found on Tegra124 chips. The EMC controls the external DRAM on the board. diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index 8fb8c1af25c9..9706550bdd5d 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -12,20 +12,26 @@ #include #include #include +#include #include #include +#include #include #include #include +#include #include #include #include #include +#include "mc.h" + #define EMC_FBIO_CFG5 0x104 #define EMC_FBIO_CFG5_DRAM_TYPE_MASK 0x3 #define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0 +#define EMC_FBIO_CFG5_DRAM_WIDTH_X64 BIT(4) #define EMC_INTSTATUS 0x0 #define EMC_INTSTATUS_CLKCHANGE_COMPLETE BIT(4) @@ -461,6 +467,17 @@ struct emc_timing { u32 emc_zcal_interval; }; +enum emc_rate_request_type { + EMC_RATE_DEBUG, + EMC_RATE_ICC, + EMC_RATE_TYPE_MAX, +}; + +struct emc_rate_request { + unsigned long min_rate; + unsigned long max_rate; +}; + struct tegra_emc { struct device *dev; @@ -471,6 +488,7 @@ struct tegra_emc { struct clk *clk; enum emc_dram_type dram_type; + unsigned int dram_bus_width; unsigned int dram_num; struct emc_timing last_timing; @@ -482,6 +500,17 @@ struct tegra_emc { unsigned long min_rate; unsigned long max_rate; } debugfs; + + struct icc_provider provider; + + /* + * There are multiple sources in the EMC driver which could request + * a min/max clock rate, these rates are contained in this array. + */ + struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX]; + + /* protect shared rate-change code path */ + struct mutex rate_lock; }; /* Timing change sequence functions */ @@ -870,6 +899,14 @@ static void emc_read_current_timing(struct tegra_emc *emc, static int emc_init(struct tegra_emc *emc) { emc->dram_type = readl(emc->regs + EMC_FBIO_CFG5); + + if (emc->dram_type & EMC_FBIO_CFG5_DRAM_WIDTH_X64) + emc->dram_bus_width = 64; + else + emc->dram_bus_width = 32; + + dev_info(emc->dev, "%ubit DRAM bus\n", emc->dram_bus_width); + emc->dram_type &= EMC_FBIO_CFG5_DRAM_TYPE_MASK; emc->dram_type >>= EMC_FBIO_CFG5_DRAM_TYPE_SHIFT; @@ -1009,6 +1046,83 @@ tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code) return NULL; } +static void tegra_emc_rate_requests_init(struct tegra_emc *emc) +{ + unsigned int i; + + for (i = 0; i < EMC_RATE_TYPE_MAX; i++) { + emc->requested_rate[i].min_rate = 0; + emc->requested_rate[i].max_rate = ULONG_MAX; + } +} + +static int emc_request_rate(struct tegra_emc *emc, + unsigned long new_min_rate, + unsigned long new_max_rate, + enum emc_rate_request_type type) +{ + struct emc_rate_request *req = emc->requested_rate; + unsigned long min_rate = 0, max_rate = ULONG_MAX; + unsigned int i; + int err; + + /* select minimum and maximum rates among the requested rates */ + for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) { + if (i == type) { + min_rate = max(new_min_rate, min_rate); + max_rate = min(new_max_rate, max_rate); + } else { + min_rate = max(req->min_rate, min_rate); + max_rate = min(req->max_rate, max_rate); + } + } + + if (min_rate > max_rate) { + dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n", + __func__, type, min_rate, max_rate); + return -ERANGE; + } + + /* + * EMC rate-changes should go via OPP API because it manages voltage + * changes. + */ + err = dev_pm_opp_set_rate(emc->dev, min_rate); + if (err) + return err; + + emc->requested_rate[type].min_rate = new_min_rate; + emc->requested_rate[type].max_rate = new_max_rate; + + return 0; +} + +static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate, + enum emc_rate_request_type type) +{ + struct emc_rate_request *req = &emc->requested_rate[type]; + int ret; + + mutex_lock(&emc->rate_lock); + ret = emc_request_rate(emc, rate, req->max_rate, type); + mutex_unlock(&emc->rate_lock); + + return ret; +} + +static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate, + enum emc_rate_request_type type) +{ + struct emc_rate_request *req = &emc->requested_rate[type]; + int ret; + + mutex_lock(&emc->rate_lock); + ret = emc_request_rate(emc, req->min_rate, rate, type); + mutex_unlock(&emc->rate_lock); + + return ret; +} + /* * debugfs interface * @@ -1081,7 +1195,7 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate) if (!tegra_emc_validate_rate(emc, rate)) return -EINVAL; - err = clk_set_min_rate(emc->clk, rate); + err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG); if (err < 0) return err; @@ -1111,7 +1225,7 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate) if (!tegra_emc_validate_rate(emc, rate)) return -EINVAL; - err = clk_set_max_rate(emc->clk, rate); + err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG); if (err < 0) return err; @@ -1129,15 +1243,6 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc) unsigned int i; int err; - emc->clk = devm_clk_get(dev, "emc"); - if (IS_ERR(emc->clk)) { - if (PTR_ERR(emc->clk) != -ENODEV) { - dev_err(dev, "failed to get EMC clock: %ld\n", - PTR_ERR(emc->clk)); - return; - } - } - emc->debugfs.min_rate = ULONG_MAX; emc->debugfs.max_rate = 0; @@ -1177,6 +1282,177 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc) emc, &tegra_emc_debug_max_rate_fops); } +static inline struct tegra_emc * +to_tegra_emc_provider(struct icc_provider *provider) +{ + return container_of(provider, struct tegra_emc, provider); +} + +static struct icc_node_data * +emc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data) +{ + struct icc_provider *provider = data; + struct icc_node_data *ndata; + struct icc_node *node; + + /* External Memory is the only possible ICC route */ + list_for_each_entry(node, &provider->nodes, node_list) { + if (node->id != TEGRA_ICC_EMEM) + continue; + + ndata = kzalloc(sizeof(*ndata), GFP_KERNEL); + if (!ndata) + return ERR_PTR(-ENOMEM); + + /* + * SRC and DST nodes should have matching TAG in order to have + * it set by default for a requested path. + */ + ndata->tag = TEGRA_MC_ICC_TAG_ISO; + ndata->node = node; + + return ndata; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static int emc_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct tegra_emc *emc = to_tegra_emc_provider(dst->provider); + unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw); + unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw); + unsigned long long rate = max(avg_bw, peak_bw); + unsigned int dram_data_bus_width_bytes; + const unsigned int ddr = 2; + int err; + + /* + * Tegra124 EMC runs on a clock rate of SDRAM bus. This means that + * EMC clock rate is twice smaller than the peak data rate because + * data is sampled on both EMC clock edges. + */ + dram_data_bus_width_bytes = emc->dram_bus_width / 8; + do_div(rate, ddr * dram_data_bus_width_bytes); + rate = min_t(u64, rate, U32_MAX); + + err = emc_set_min_rate(emc, rate, EMC_RATE_ICC); + if (err) + return err; + + return 0; +} + +static int tegra_emc_interconnect_init(struct tegra_emc *emc) +{ + const struct tegra_mc_soc *soc = emc->mc->soc; + struct icc_node *node; + int err; + + emc->provider.dev = emc->dev; + emc->provider.set = emc_icc_set; + emc->provider.data = &emc->provider; + emc->provider.aggregate = soc->icc_ops->aggregate; + emc->provider.xlate_extended = emc_of_icc_xlate_extended; + + err = icc_provider_add(&emc->provider); + if (err) + goto err_msg; + + /* create External Memory Controller node */ + node = icc_node_create(TEGRA_ICC_EMC); + if (IS_ERR(node)) { + err = PTR_ERR(node); + goto del_provider; + } + + node->name = "External Memory Controller"; + icc_node_add(node, &emc->provider); + + /* link External Memory Controller to External Memory (DRAM) */ + err = icc_link_create(node, TEGRA_ICC_EMEM); + if (err) + goto remove_nodes; + + /* create External Memory node */ + node = icc_node_create(TEGRA_ICC_EMEM); + if (IS_ERR(node)) { + err = PTR_ERR(node); + goto remove_nodes; + } + + node->name = "External Memory (DRAM)"; + icc_node_add(node, &emc->provider); + + return 0; + +remove_nodes: + icc_nodes_remove(&emc->provider); +del_provider: + icc_provider_del(&emc->provider); +err_msg: + dev_err(emc->dev, "failed to initialize ICC: %d\n", err); + + return err; +} + +static int tegra_emc_opp_table_init(struct tegra_emc *emc) +{ + u32 hw_version = BIT(tegra_sku_info.soc_speedo_id); + struct opp_table *clk_opp_table, *hw_opp_table; + int err; + + clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL); + err = PTR_ERR_OR_ZERO(clk_opp_table); + if (err) { + dev_err(emc->dev, "failed to set OPP clk: %d\n", err); + return err; + } + + hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1); + err = PTR_ERR_OR_ZERO(hw_opp_table); + if (err) { + dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err); + goto put_clk_table; + } + + err = dev_pm_opp_of_add_table(emc->dev); + if (err) { + if (err == -ENODEV) + dev_err(emc->dev, "OPP table not found, please update your device tree\n"); + else + dev_err(emc->dev, "failed to add OPP table: %d\n", err); + + goto put_hw_table; + } + + dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n", + hw_version, clk_get_rate(emc->clk) / 1000000); + + /* first dummy rate-set initializes voltage state */ + err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk)); + if (err) { + dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err); + goto remove_table; + } + + return 0; + +remove_table: + dev_pm_opp_of_remove_table(emc->dev); +put_hw_table: + dev_pm_opp_put_supported_hw(hw_opp_table); +put_clk_table: + dev_pm_opp_put_clkname(clk_opp_table); + + return err; +} + +static void devm_tegra_emc_unset_callback(void *data) +{ + tegra124_clk_set_emc_callbacks(NULL, NULL); +} + static int tegra_emc_probe(struct platform_device *pdev) { struct device_node *np; @@ -1188,6 +1464,7 @@ static int tegra_emc_probe(struct platform_device *pdev) if (!emc) return -ENOMEM; + mutex_init(&emc->rate_lock); emc->dev = &pdev->dev; emc->regs = devm_platform_ioremap_resource(pdev, 0); @@ -1223,9 +1500,29 @@ static int tegra_emc_probe(struct platform_device *pdev) tegra124_clk_set_emc_callbacks(tegra_emc_prepare_timing_change, tegra_emc_complete_timing_change); + err = devm_add_action_or_reset(&pdev->dev, devm_tegra_emc_unset_callback, + NULL); + if (err) + return err; + + emc->clk = devm_clk_get(&pdev->dev, "emc"); + if (IS_ERR(emc->clk)) { + err = PTR_ERR(emc->clk); + dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err); + return err; + } + + err = tegra_emc_opp_table_init(emc); + if (err) + return err; + + tegra_emc_rate_requests_init(emc); + if (IS_ENABLED(CONFIG_DEBUG_FS)) emc_debugfs_init(&pdev->dev, emc); + tegra_emc_interconnect_init(emc); + /* * Don't allow the kernel module to be unloaded. Unloading adds some * extra complexity which doesn't really worth the effort in a case of @@ -1242,6 +1539,7 @@ static struct platform_driver tegra_emc_driver = { .name = "tegra-emc", .of_match_table = tegra_emc_of_match, .suppress_bind_attrs = true, + .sync_state = icc_sync_state, }, }; module_platform_driver(tegra_emc_driver); diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index e2389573d3c0..459211f50c08 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -4,7 +4,8 @@ */ #include -#include +#include +#include #include @@ -1010,6 +1011,83 @@ static const struct tegra_mc_reset tegra124_mc_resets[] = { TEGRA124_MC_RESET(GPU, 0x970, 0x974, 2), }; +static int tegra124_mc_icc_set(struct icc_node *src, struct icc_node *dst) +{ + /* TODO: program PTSA */ + return 0; +} + +static int tegra124_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + /* + * ISO clients need to reserve extra bandwidth up-front because + * there could be high bandwidth pressure during initial filling + * of the client's FIFO buffers. Secondly, we need to take into + * account impurities of the memory subsystem. + */ + if (tag & TEGRA_MC_ICC_TAG_ISO) + peak_bw = tegra_mc_scale_percents(peak_bw, 400); + + *agg_avg += avg_bw; + *agg_peak = max(*agg_peak, peak_bw); + + return 0; +} + +static struct icc_node_data * +tegra124_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data) +{ + struct tegra_mc *mc = icc_provider_to_tegra_mc(data); + const struct tegra_mc_client *client; + unsigned int i, idx = spec->args[0]; + struct icc_node_data *ndata; + struct icc_node *node; + + list_for_each_entry(node, &mc->provider.nodes, node_list) { + if (node->id != idx) + continue; + + ndata = kzalloc(sizeof(*ndata), GFP_KERNEL); + if (!ndata) + return ERR_PTR(-ENOMEM); + + client = &mc->soc->clients[idx]; + ndata->node = node; + + switch (client->swgroup) { + case TEGRA_SWGROUP_DC: + case TEGRA_SWGROUP_DCB: + case TEGRA_SWGROUP_PTC: + case TEGRA_SWGROUP_VI: + /* these clients are isochronous by default */ + ndata->tag = TEGRA_MC_ICC_TAG_ISO; + break; + + default: + ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT; + break; + } + + return ndata; + } + + for (i = 0; i < mc->soc->num_clients; i++) { + if (mc->soc->clients[i].id == idx) + return ERR_PTR(-EPROBE_DEFER); + } + + dev_err(mc->dev, "invalid ICC client ID %u\n", idx); + + return ERR_PTR(-EINVAL); +} + +static const struct tegra_mc_icc_ops tegra124_mc_icc_ops = { + .xlate_extended = tegra124_mc_of_icc_xlate_extended, + .aggregate = tegra124_mc_icc_aggreate, + .set = tegra124_mc_icc_set, +}; + #ifdef CONFIG_ARCH_TEGRA_124_SOC static const unsigned long tegra124_mc_emem_regs[] = { MC_EMEM_ARB_CFG, @@ -1061,6 +1139,7 @@ const struct tegra_mc_soc tegra124_mc_soc = { .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), + .icc_ops = &tegra124_mc_icc_ops, }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1091,5 +1170,6 @@ const struct tegra_mc_soc tegra132_mc_soc = { .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), + .icc_ops = &tegra124_mc_icc_ops, }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ -- cgit v1.2.3 From 8e9199189443b39a0c3db629150610b832af9ac8 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sat, 2 Jan 2021 05:54:09 -0600 Subject: dt-bindings: memory: renesas,rpc-if: Add support for RZ/G2 Series The RZ/G2 Series has the RPC-IF interface. Update bindings to support: r8a774a1, r8a774b1, r8a774c0, and r8a774e1 Signed-off-by: Adam Ford Link: https://lore.kernel.org/r/20210102115412.3402059-1-aford173@gmail.com Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/memory-controllers/renesas,rpc-if.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml index 6d6ba608fd22..990489fdd2ac 100644 --- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml @@ -26,10 +26,14 @@ properties: compatible: items: - enum: + - renesas,r8a774a1-rpc-if # RZ/G2M + - renesas,r8a774b1-rpc-if # RZ/G2N + - renesas,r8a774c0-rpc-if # RZ/G2E + - renesas,r8a774e1-rpc-if # RZ/G2H - renesas,r8a77970-rpc-if # R-Car V3M - renesas,r8a77980-rpc-if # R-Car V3H - renesas,r8a77995-rpc-if # R-Car D3 - - const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 device + - const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 or RZ/G2 device reg: items: -- cgit v1.2.3 From 409f9fe9db242cb15994feacfb5035d9ef586c67 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sat, 2 Jan 2021 05:54:10 -0600 Subject: memory: renesas-rpc-if: Add RZ/G2 to Kconfig description The Renesas RPC-IF is present on the RZ/G2 Series. Add that to the description. Suggested-by: Biju Das Signed-off-by: Adam Ford Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210102115412.3402059-2-aford173@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 3ea6913df176..7e01b5157f40 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -202,9 +202,9 @@ config RENESAS_RPCIF depends on ARCH_RENESAS || COMPILE_TEST select REGMAP_MMIO help - This supports Renesas R-Car Gen3 RPC-IF which provides either SPI - host or HyperFlash. You'll have to select individual components - under the corresponding menu. + This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides + either SPI host or HyperFlash. You'll have to select individual + components under the corresponding menu. config STM32_FMC2_EBI tristate "Support for FMC2 External Bus Interface on STM32MP SoCs" -- cgit v1.2.3 From dd820ee21d5e0795096a6e0e47c0183d96464949 Mon Sep 17 00:00:00 2001 From: Jim Quinlan Date: Tue, 22 Dec 2020 09:56:03 -0500 Subject: firmware: arm_scmi: Augment SMC/HVC to allow optional interrupt The SMC/HVC SCMI transport is modified to allow the completion of an SCMI message to be indicated by an interrupt rather than the return of the smc/hvc call. This accommodates the existing behavior of the BrcmSTB SCMI "platform". Link: https://lore.kernel.org/r/20201222145603.40192-3-jim2101024@gmail.com Signed-off-by: Jim Quinlan [sudeep.holla: added call to reinit_completion, whitespace cleanup, dropped irrelavant info in the commit log] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/smc.c | 42 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index 82a82a5dc86a..fcbe2677f84b 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include #include "common.h" @@ -23,6 +25,8 @@ * @shmem: Transmit/Receive shared memory area * @shmem_lock: Lock to protect access to Tx/Rx shared memory area * @func_id: smc/hvc call function id + * @irq: Optional; employed when platforms indicates msg completion by intr. + * @tx_complete: Optional, employed only when irq is valid. */ struct scmi_smc { @@ -30,8 +34,19 @@ struct scmi_smc { struct scmi_shared_mem __iomem *shmem; struct mutex shmem_lock; u32 func_id; + int irq; + struct completion tx_complete; }; +static irqreturn_t smc_msg_done_isr(int irq, void *data) +{ + struct scmi_smc *scmi_info = data; + + complete(&scmi_info->tx_complete); + + return IRQ_HANDLED; +} + static bool smc_chan_available(struct device *dev, int idx) { struct device_node *np = of_parse_phandle(dev->of_node, "shmem", 0); @@ -51,7 +66,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, struct resource res; struct device_node *np; u32 func_id; - int ret; + int ret, irq; if (!tx) return -ENODEV; @@ -79,6 +94,24 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (ret < 0) return ret; + /* + * If there is an interrupt named "a2p", then the service and + * completion of a message is signaled by an interrupt rather than by + * the return of the SMC call. + */ + irq = of_irq_get_byname(cdev->of_node, "a2p"); + if (irq > 0) { + ret = devm_request_irq(dev, irq, smc_msg_done_isr, + IRQF_NO_SUSPEND, + dev_name(dev), scmi_info); + if (ret) { + dev_err(dev, "failed to setup SCMI smc irq\n"); + return ret; + } + init_completion(&scmi_info->tx_complete); + scmi_info->irq = irq; + } + scmi_info->func_id = func_id; scmi_info->cinfo = cinfo; mutex_init(&scmi_info->shmem_lock); @@ -110,7 +143,14 @@ static int smc_send_message(struct scmi_chan_info *cinfo, shmem_tx_prepare(scmi_info->shmem, xfer); + if (scmi_info->irq) + reinit_completion(&scmi_info->tx_complete); + arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); + + if (scmi_info->irq) + wait_for_completion(&scmi_info->tx_complete); + scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem)); mutex_unlock(&scmi_info->shmem_lock); -- cgit v1.2.3 From 6054d97ab512732239391a5c24f044e4f042a062 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 5 Jan 2021 15:19:45 +0000 Subject: MAINTAINERS: Update ARM SCMI entry Cristian is actively developing new features and more involved than me. So add Cristian as a designated reviewer. Also add the newly added scmi regulator driver to the list. Link: https://lore.kernel.org/r/20210105151945.406093-1-sudeep.holla@arm.com Cc: Cristian Marussi Acked-by: Cristian Marussi Signed-off-by: Sudeep Holla --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..7a22b8b0f5d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17208,6 +17208,7 @@ F: drivers/mfd/syscon.c SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers M: Sudeep Holla +R: Cristian Marussi L: linux-arm-kernel@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt @@ -17215,6 +17216,7 @@ F: drivers/clk/clk-sc[mp]i.c F: drivers/cpufreq/sc[mp]i-cpufreq.c F: drivers/firmware/arm_scmi/ F: drivers/firmware/arm_scpi.c +F: drivers/regulator/scmi-regulator.c F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h F: include/trace/events/scmi.h -- cgit v1.2.3 From 014d65b60e46e1af262419139c07bfa1f0775715 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:32 -0600 Subject: bus: sunxi-rsb: Move OF match table For some reason, this driver's OF match table was placed above the probe/remove functions, far away from the platform_driver definition. Adding device PM ops would move the table even farther away. Let's move it to the usual place, right before the platform_driver. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 1bb00a959c67..c13340cab27a 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -614,12 +614,6 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb) return 0; } -static const struct of_device_id sunxi_rsb_of_match_table[] = { - { .compatible = "allwinner,sun8i-a23-rsb" }, - {} -}; -MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); - static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -747,6 +741,12 @@ static int sunxi_rsb_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id sunxi_rsb_of_match_table[] = { + { .compatible = "allwinner,sun8i-a23-rsb" }, + {} +}; +MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); + static struct platform_driver sunxi_rsb_driver = { .probe = sunxi_rsb_probe, .remove = sunxi_rsb_remove, -- cgit v1.2.3 From 22754ac9a632f9bcb2cfd91243459e679778a497 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:33 -0600 Subject: bus: sunxi-rsb: Split out controller init/exit functions This separates the resource acquisition from the hardware initialization phase, so the hardware initialization can be repeated after system suspend/resume. The same is done for the exit/remove function, except that there is no resource deallocation phase due to the use of devres. The requested RSB clock frequency is stored in `struct sunxi_rsb` so it will be available when reinitializing the hardware. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 127 +++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index c13340cab27a..3f290da45619 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -126,6 +126,7 @@ struct sunxi_rsb { struct completion complete; struct mutex lock; unsigned int status; + u32 clk_freq; }; /* bus / slave device related functions */ @@ -614,16 +615,74 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb) return 0; } +static int sunxi_rsb_hw_init(struct sunxi_rsb *rsb) +{ + struct device *dev = rsb->dev; + unsigned long p_clk_freq; + u32 clk_delay, reg; + int clk_div, ret; + + ret = clk_prepare_enable(rsb->clk); + if (ret) { + dev_err(dev, "failed to enable clk: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(rsb->rstc); + if (ret) { + dev_err(dev, "failed to deassert reset line: %d\n", ret); + goto err_clk_disable; + } + + /* reset the controller */ + writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL); + readl_poll_timeout(rsb->regs + RSB_CTRL, reg, + !(reg & RSB_CTRL_SOFT_RST), 1000, 100000); + + /* + * Clock frequency and delay calculation code is from + * Allwinner U-boot sources. + * + * From A83 user manual: + * bus clock frequency = parent clock frequency / (2 * (divider + 1)) + */ + p_clk_freq = clk_get_rate(rsb->clk); + clk_div = p_clk_freq / rsb->clk_freq / 2; + if (!clk_div) + clk_div = 1; + else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1) + clk_div = RSB_CCR_MAX_CLK_DIV + 1; + + clk_delay = clk_div >> 1; + if (!clk_delay) + clk_delay = 1; + + dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2); + writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1), + rsb->regs + RSB_CCR); + + return 0; + +err_clk_disable: + clk_disable_unprepare(rsb->clk); + + return ret; +} + +static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) +{ + reset_control_assert(rsb->rstc); + clk_disable_unprepare(rsb->clk); +} + static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct resource *r; struct sunxi_rsb *rsb; - unsigned long p_clk_freq; - u32 clk_delay, clk_freq = 3000000; - int clk_div, irq, ret; - u32 reg; + u32 clk_freq = 3000000; + int irq, ret; of_property_read_u32(np, "clock-frequency", &clk_freq); if (clk_freq > RSB_MAX_FREQ) { @@ -638,6 +697,7 @@ static int sunxi_rsb_probe(struct platform_device *pdev) return -ENOMEM; rsb->dev = dev; + rsb->clk_freq = clk_freq; platform_set_drvdata(pdev, rsb); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); rsb->regs = devm_ioremap_resource(dev, r); @@ -655,63 +715,27 @@ static int sunxi_rsb_probe(struct platform_device *pdev) return ret; } - ret = clk_prepare_enable(rsb->clk); - if (ret) { - dev_err(dev, "failed to enable clk: %d\n", ret); - return ret; - } - - p_clk_freq = clk_get_rate(rsb->clk); - rsb->rstc = devm_reset_control_get(dev, NULL); if (IS_ERR(rsb->rstc)) { ret = PTR_ERR(rsb->rstc); dev_err(dev, "failed to retrieve reset controller: %d\n", ret); - goto err_clk_disable; - } - - ret = reset_control_deassert(rsb->rstc); - if (ret) { - dev_err(dev, "failed to deassert reset line: %d\n", ret); - goto err_clk_disable; + return ret; } init_completion(&rsb->complete); mutex_init(&rsb->lock); - /* reset the controller */ - writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL); - readl_poll_timeout(rsb->regs + RSB_CTRL, reg, - !(reg & RSB_CTRL_SOFT_RST), 1000, 100000); - - /* - * Clock frequency and delay calculation code is from - * Allwinner U-boot sources. - * - * From A83 user manual: - * bus clock frequency = parent clock frequency / (2 * (divider + 1)) - */ - clk_div = p_clk_freq / clk_freq / 2; - if (!clk_div) - clk_div = 1; - else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1) - clk_div = RSB_CCR_MAX_CLK_DIV + 1; - - clk_delay = clk_div >> 1; - if (!clk_delay) - clk_delay = 1; - - dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2); - writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1), - rsb->regs + RSB_CCR); - ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb); if (ret) { dev_err(dev, "can't register interrupt handler irq %d: %d\n", irq, ret); - goto err_reset_assert; + return ret; } + ret = sunxi_rsb_hw_init(rsb); + if (ret) + return ret; + /* initialize all devices on the bus into RSB mode */ ret = sunxi_rsb_init_device_mode(rsb); if (ret) @@ -720,14 +744,6 @@ static int sunxi_rsb_probe(struct platform_device *pdev) of_rsb_register_devices(rsb); return 0; - -err_reset_assert: - reset_control_assert(rsb->rstc); - -err_clk_disable: - clk_disable_unprepare(rsb->clk); - - return ret; } static int sunxi_rsb_remove(struct platform_device *pdev) @@ -735,8 +751,7 @@ static int sunxi_rsb_remove(struct platform_device *pdev) struct sunxi_rsb *rsb = platform_get_drvdata(pdev); device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices); - reset_control_assert(rsb->rstc); - clk_disable_unprepare(rsb->clk); + sunxi_rsb_hw_exit(rsb); return 0; } -- cgit v1.2.3 From 843107498f91e57d1d4b22cd8787112726fdaeb4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:34 -0600 Subject: bus: sunxi-rsb: Implement suspend/resume/shutdown callbacks Since system firmware is likely to use the RSB bus to communicate with a PMIC while the system is suspended, we cannot make any assumptions about the controller state after resuming. Thus it is important to completely reinitialize the controller. The RSB bus needs to be ready as soon as IRQs are enabled, to handle wakeup event IRQs coming from the PMIC. Thus it uses NOIRQ callbacks. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 3f290da45619..efd222f36cdc 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -675,6 +676,22 @@ static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) clk_disable_unprepare(rsb->clk); } +static int __maybe_unused sunxi_rsb_suspend(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + sunxi_rsb_hw_exit(rsb); + + return 0; +} + +static int __maybe_unused sunxi_rsb_resume(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + return sunxi_rsb_hw_init(rsb); +} + static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -756,6 +773,17 @@ static int sunxi_rsb_remove(struct platform_device *pdev) return 0; } +static void sunxi_rsb_shutdown(struct platform_device *pdev) +{ + struct sunxi_rsb *rsb = platform_get_drvdata(pdev); + + sunxi_rsb_hw_exit(rsb); +} + +static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sunxi_rsb_suspend, sunxi_rsb_resume) +}; + static const struct of_device_id sunxi_rsb_of_match_table[] = { { .compatible = "allwinner,sun8i-a23-rsb" }, {} @@ -765,9 +793,11 @@ MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); static struct platform_driver sunxi_rsb_driver = { .probe = sunxi_rsb_probe, .remove = sunxi_rsb_remove, + .shutdown = sunxi_rsb_shutdown, .driver = { .name = RSB_CTRL_NAME, .of_match_table = sunxi_rsb_of_match_table, + .pm = &sunxi_rsb_dev_pm_ops, }, }; -- cgit v1.2.3 From 4a0dbc12e61823ece7172df953c3333c8f5f9222 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:35 -0600 Subject: bus: sunxi-rsb: Implement runtime power management Gate the clock to save power while the controller is idle. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index efd222f36cdc..ba5100dfc413 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -337,6 +338,10 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, return -EINVAL; } + ret = pm_runtime_resume_and_get(rsb->dev); + if (ret) + return ret; + mutex_lock(&rsb->lock); writel(addr, rsb->regs + RSB_ADDR); @@ -352,6 +357,9 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, unlock: mutex_unlock(&rsb->lock); + pm_runtime_mark_last_busy(rsb->dev); + pm_runtime_put_autosuspend(rsb->dev); + return ret; } @@ -379,6 +387,10 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, return -EINVAL; } + ret = pm_runtime_resume_and_get(rsb->dev); + if (ret) + return ret; + mutex_lock(&rsb->lock); writel(addr, rsb->regs + RSB_ADDR); @@ -389,6 +401,9 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, mutex_unlock(&rsb->lock); + pm_runtime_mark_last_busy(rsb->dev); + pm_runtime_put_autosuspend(rsb->dev); + return ret; } @@ -672,10 +687,29 @@ err_clk_disable: static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) { + /* Keep the clock and PM reference counts consistent. */ + if (pm_runtime_status_suspended(rsb->dev)) + pm_runtime_resume(rsb->dev); reset_control_assert(rsb->rstc); clk_disable_unprepare(rsb->clk); } +static int __maybe_unused sunxi_rsb_runtime_suspend(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + clk_disable_unprepare(rsb->clk); + + return 0; +} + +static int __maybe_unused sunxi_rsb_runtime_resume(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + return clk_prepare_enable(rsb->clk); +} + static int __maybe_unused sunxi_rsb_suspend(struct device *dev) { struct sunxi_rsb *rsb = dev_get_drvdata(dev); @@ -758,6 +792,12 @@ static int sunxi_rsb_probe(struct platform_device *pdev) if (ret) dev_warn(dev, "Initialize device mode failed: %d\n", ret); + pm_suspend_ignore_children(dev, true); + pm_runtime_set_active(dev); + pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); + of_rsb_register_devices(rsb); return 0; @@ -768,6 +808,7 @@ static int sunxi_rsb_remove(struct platform_device *pdev) struct sunxi_rsb *rsb = platform_get_drvdata(pdev); device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices); + pm_runtime_disable(&pdev->dev); sunxi_rsb_hw_exit(rsb); return 0; @@ -777,10 +818,13 @@ static void sunxi_rsb_shutdown(struct platform_device *pdev) { struct sunxi_rsb *rsb = platform_get_drvdata(pdev); + pm_runtime_disable(&pdev->dev); sunxi_rsb_hw_exit(rsb); } static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = { + SET_RUNTIME_PM_OPS(sunxi_rsb_runtime_suspend, + sunxi_rsb_runtime_resume, NULL) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sunxi_rsb_suspend, sunxi_rsb_resume) }; -- cgit v1.2.3 From fef419c463d0dd95488a9750dc501ae43825e5d2 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 7 Jan 2021 14:09:30 +0530 Subject: soc: qcom: rpmh: Remove serialization of TCS commands Requests sent to RPMH can be sent as fire-n-forget or response required, with the latter ensuring the command has been completed by the hardware accelerator. Commands in a request with tcs_cmd::wait set, would ensure that those select commands are sent as response required, even though the actual TCS request may be fire-n-forget. Also, commands with .wait flag were also guaranteed to be complete before the following command in the TCS is sent. This means that the next command of the same request blocked until the current request is completed. This could mean waiting for a voltage to settle or series of NOCs be configured before the next command is sent. But drivers using this feature have never cared about the serialization aspect. By not enforcing the serialization we can allow the hardware to run in parallel improving the performance. Let's clarify the usage of this member in the tcs_cmd structure to mean only completion and not serialization. This should also improve the performance of bus requests where changes could happen in parallel. Also, CPU resume from deep idle may see benefits from certain wake requests. Reviewed-by: Douglas Anderson Signed-off-by: Lina Iyer Signed-off-by: Maulik Shah Link: https://lore.kernel.org/r/1610008770-13891-1-git-send-email-mkshah@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 22 +++++++++------------- include/soc/qcom/tcs.h | 9 ++++++++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 0b082ec894a1..a84ab0d6a9d4 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -231,10 +231,9 @@ static void tcs_invalidate(struct rsc_drv *drv, int type) if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS)) return; - for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) { + for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); - write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0); - } + bitmap_zero(tcs->slots, MAX_TCS_SLOTS); } @@ -443,7 +442,6 @@ static irqreturn_t tcs_tx_done(int irq, void *p) skip: /* Reclaim the TCS */ write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); - write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0); writel_relaxed(BIT(i), drv->tcs_base + RSC_DRV_IRQ_CLEAR); spin_lock(&drv->lock); clear_bit(i, drv->tcs_in_use); @@ -476,23 +474,23 @@ skip: static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, const struct tcs_request *msg) { - u32 msgid, cmd_msgid; + u32 msgid; + u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE; u32 cmd_enable = 0; - u32 cmd_complete; struct tcs_cmd *cmd; int i, j; - cmd_msgid = CMD_MSGID_LEN; + /* Convert all commands to RR when the request has wait_for_compl set */ cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; - cmd_msgid |= CMD_MSGID_WRITE; - - cmd_complete = read_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id); for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) { cmd = &msg->cmds[i]; cmd_enable |= BIT(j); - cmd_complete |= cmd->wait << j; msgid = cmd_msgid; + /* + * Additionally, if the cmd->wait is set, make the command + * response reqd even if the overall request was fire-n-forget. + */ msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); @@ -501,7 +499,6 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); } - write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete); cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id); write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable); } @@ -652,7 +649,6 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate() */ write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); - write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0); enable_tcs_irq(drv, tcs_id, true); } spin_unlock_irqrestore(&drv->lock, flags); diff --git a/include/soc/qcom/tcs.h b/include/soc/qcom/tcs.h index 7a2a055ba6b0..3acca067c72b 100644 --- a/include/soc/qcom/tcs.h +++ b/include/soc/qcom/tcs.h @@ -30,7 +30,13 @@ enum rpmh_state { * * @addr: the address of the resource slv_id:18:16 | offset:0:15 * @data: the resource state request - * @wait: wait for this request to be complete before sending the next + * @wait: ensure that this command is complete before returning. + * Setting "wait" here only makes sense during rpmh_write_batch() for + * active-only transfers, this is because: + * rpmh_write() - Always waits. + * (DEFINE_RPMH_MSG_ONSTACK will set .wait_for_compl) + * rpmh_write_async() - Never waits. + * (There's no request completion callback) */ struct tcs_cmd { u32 addr; @@ -43,6 +49,7 @@ struct tcs_cmd { * * @state: state for the request. * @wait_for_compl: wait until we get a response from the h/w accelerator + * (same as setting cmd->wait for all commands in the request) * @num_cmds: the number of @cmds in this request * @cmds: an array of tcs_cmds */ -- cgit v1.2.3 From 9fc33807ad2967e3acd848a8be1b11bb082d87e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 27 Nov 2020 12:14:41 +0100 Subject: dt-bindings: reset: document Broadcom's BCM4908 PCIe reset binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM4908 was built using older PCIe hardware block that requires using external reset block controlling PERST# signals. Signed-off-by: RafaÅ‚ MiÅ‚ecki Acked-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../reset/brcm,bcm4908-misc-pcie-reset.yaml | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/brcm,bcm4908-misc-pcie-reset.yaml diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm4908-misc-pcie-reset.yaml b/Documentation/devicetree/bindings/reset/brcm,bcm4908-misc-pcie-reset.yaml new file mode 100644 index 000000000000..88aebb370838 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/brcm,bcm4908-misc-pcie-reset.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/brcm,bcm4908-misc-pcie-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom MISC block PCIe reset controller + +description: This document describes reset controller handling PCIe PERST# + signals. On BCM4908 it's a part of the MISC block. + +maintainers: + - RafaÅ‚ MiÅ‚ecki + +properties: + compatible: + const: brcm,bcm4908-misc-pcie-reset + + reg: + maxItems: 1 + + "#reset-cells": + description: PCIe core id + const: 1 + +required: + - compatible + - reg + - "#reset-cells" + +additionalProperties: false + +examples: + - | + reset-controller@ff802644 { + compatible = "brcm,bcm4908-misc-pcie-reset"; + reg = <0xff802644 0x04>; + #reset-cells = <1>; + }; -- cgit v1.2.3 From def26913b66fd94e431afecf28e09c08e8c02a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 27 Nov 2020 12:14:42 +0100 Subject: reset: simple: add BCM4908 MISC PCIe reset controller support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a trivial reset controller. One register with bit per PCIe core. Signed-off-by: RafaÅ‚ MiÅ‚ecki Acked-by: Florian Fainelli Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 2 +- drivers/reset/reset-simple.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 71ab75a46491..752bef7e564f 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -173,7 +173,7 @@ config RESET_SCMI config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST - default ARCH_AGILEX || ARCH_ASPEED || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARC + default ARCH_AGILEX || ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARC help This enables a simple reset controller driver for reset lines that that can be asserted and deasserted by toggling bits in a contiguous, diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index e066614818a3..4dda0daf2c6f 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -146,6 +146,8 @@ static const struct of_device_id reset_simple_dt_ids[] = { { .compatible = "aspeed,ast2500-lpc-reset" }, { .compatible = "bitmain,bm1880-reset", .data = &reset_simple_active_low }, + { .compatible = "brcm,bcm4908-misc-pcie-reset", + .data = &reset_simple_active_low }, { .compatible = "snps,dw-high-reset" }, { .compatible = "snps,dw-low-reset", .data = &reset_simple_active_low }, -- cgit v1.2.3 From e0d1662443ee0ee275bb5a8ab4c53d0739313290 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 8 Dec 2020 20:46:38 +0800 Subject: reset: hisilicon: correct vendor prefix The vendor prefix of "Hisilicon Limited" is "hisilicon", it is clearly stated in "vendor-prefixes.yaml". For backward compatibility reasons fall back to the deprecated compatible if the new one failed. Fixes: 1527058736fa ("reset: hisilicon: add reset-hi3660") Signed-off-by: Zhen Lei Cc: Zhangfei Gao Signed-off-by: Philipp Zabel --- drivers/reset/hisilicon/reset-hi3660.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/reset/hisilicon/reset-hi3660.c b/drivers/reset/hisilicon/reset-hi3660.c index a7d4445924e5..965f5ceba7d8 100644 --- a/drivers/reset/hisilicon/reset-hi3660.c +++ b/drivers/reset/hisilicon/reset-hi3660.c @@ -83,9 +83,14 @@ static int hi3660_reset_probe(struct platform_device *pdev) if (!rc) return -ENOMEM; - rc->map = syscon_regmap_lookup_by_phandle(np, "hisi,rst-syscon"); + rc->map = syscon_regmap_lookup_by_phandle(np, "hisilicon,rst-syscon"); + if (rc->map == ERR_PTR(-ENODEV)) { + /* fall back to the deprecated compatible */ + rc->map = syscon_regmap_lookup_by_phandle(np, + "hisi,rst-syscon"); + } if (IS_ERR(rc->map)) { - dev_err(dev, "failed to get hi3660,rst-syscon\n"); + dev_err(dev, "failed to get hisilicon,rst-syscon\n"); return PTR_ERR(rc->map); } -- cgit v1.2.3 From 0cafb846a326e838d41db22f96e625c0ad0b6fc8 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 8 Dec 2020 20:46:40 +0800 Subject: dt-bindings: reset: correct vendor prefix hisi to hisilicon The vendor prefix of "Hisilicon Limited" is "hisilicon", it is clearly stated in "vendor-prefixes.yaml". Fixes: 836e23549583 ("dt-bindings: Document the hi3660 reset bindings") Signed-off-by: Zhen Lei Cc: Zhangfei Gao Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt index 2df4bddeb688..aefd26710f9e 100644 --- a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt +++ b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt @@ -11,7 +11,7 @@ Required properties: - compatible: should be one of the following: "hisilicon,hi3660-reset" for HI3660 "hisilicon,hi3670-reset", "hisilicon,hi3660-reset" for HI3670 -- hisi,rst-syscon: phandle of the reset's syscon. +- hisilicon,rst-syscon: phandle of the reset's syscon. - #reset-cells : Specifies the number of cells needed to encode a reset source. The type shall be a and the value shall be 2. @@ -29,7 +29,7 @@ Example: iomcu_rst: iomcu_rst_controller { compatible = "hisilicon,hi3660-reset"; - hisi,rst-syscon = <&iomcu>; + hisilicon,rst-syscon = <&iomcu>; #reset-cells = <2>; }; -- cgit v1.2.3 From f2ad9bfd4dda69175b8ed2c38f115c8138239780 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 8 Dec 2020 20:46:41 +0800 Subject: dt-bindings: reset: convert Hisilicon reset controller bindings to json-schema Convert the Hisilicon reset controller binding to DT schema format using json-schema. Signed-off-by: Zhen Lei Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../bindings/reset/hisilicon,hi3660-reset.txt | 44 ------------- .../bindings/reset/hisilicon,hi3660-reset.yaml | 77 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 44 deletions(-) delete mode 100644 Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt create mode 100644 Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml diff --git a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt deleted file mode 100644 index aefd26710f9e..000000000000 --- a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt +++ /dev/null @@ -1,44 +0,0 @@ -Hisilicon System Reset Controller -====================================== - -Please also refer to reset.txt in this directory for common reset -controller binding usage. - -The reset controller registers are part of the system-ctl block on -hi3660 and hi3670 SoCs. - -Required properties: -- compatible: should be one of the following: - "hisilicon,hi3660-reset" for HI3660 - "hisilicon,hi3670-reset", "hisilicon,hi3660-reset" for HI3670 -- hisilicon,rst-syscon: phandle of the reset's syscon. -- #reset-cells : Specifies the number of cells needed to encode a - reset source. The type shall be a and the value shall be 2. - - Cell #1 : offset of the reset assert control - register from the syscon register base - offset + 4: deassert control register - offset + 8: status control register - Cell #2 : bit position of the reset in the reset control register - -Example: - iomcu: iomcu@ffd7e000 { - compatible = "hisilicon,hi3660-iomcu", "syscon"; - reg = <0x0 0xffd7e000 0x0 0x1000>; - }; - - iomcu_rst: iomcu_rst_controller { - compatible = "hisilicon,hi3660-reset"; - hisilicon,rst-syscon = <&iomcu>; - #reset-cells = <2>; - }; - -Specifying reset lines connected to IP modules -============================================== -example: - - i2c0: i2c@..... { - ... - resets = <&iomcu_rst 0x20 3>; /* offset: 0x20; bit: 3 */ - ... - }; diff --git a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml new file mode 100644 index 000000000000..9bf40952e5b7 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/hisilicon,hi3660-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Hisilicon System Reset Controller + +maintainers: + - Wei Xu + +description: | + Please also refer to reset.txt in this directory for common reset + controller binding usage. + The reset controller registers are part of the system-ctl block on + hi3660 and hi3670 SoCs. + +properties: + compatible: + oneOf: + - items: + - const: hisilicon,hi3660-reset + - items: + - const: hisilicon,hi3670-reset + - const: hisilicon,hi3660-reset + + hisilicon,rst-syscon: + description: phandle of the reset's syscon. + $ref: /schemas/types.yaml#/definitions/phandle + + '#reset-cells': + description: | + Specifies the number of cells needed to encode a reset source. + Cell #1 : offset of the reset assert control register from the syscon + register base + offset + 4: deassert control register + offset + 8: status control register + Cell #2 : bit position of the reset in the reset control register + const: 2 + +required: + - compatible + +additionalProperties: false + +examples: + - | + #include + #include + #include + + iomcu: iomcu@ffd7e000 { + compatible = "hisilicon,hi3660-iomcu", "syscon"; + reg = <0xffd7e000 0x1000>; + }; + + iomcu_rst: iomcu_rst_controller { + compatible = "hisilicon,hi3660-reset"; + hisilicon,rst-syscon = <&iomcu>; + #reset-cells = <2>; + }; + + /* Specifying reset lines connected to IP modules */ + i2c@ffd71000 { + compatible = "snps,designware-i2c"; + reg = <0xffd71000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + clocks = <&crg_ctrl HI3660_CLK_GATE_I2C0>; + resets = <&iomcu_rst 0x20 3>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pmx_func &i2c0_cfg_func>; + status = "disabled"; + }; +... -- cgit v1.2.3 From 7d981405d0fd3cfc0de052e4791f516235d8b858 Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Mon, 4 Jan 2021 17:15:44 +0800 Subject: soc: imx8m: change to use platform driver Directly reading ocotp register depends on that bootloader enables ocotp clk, which is not always effective, so change to use nvmem API. Using nvmem API requires to support driver defer probe and thus change soc-imx8m.c to use platform driver. The other reason is that directly reading ocotp register causes kexec kernel hang because the 1st kernel running will disable unused clks after kernel boots up, and then ocotp clk will be disabled even if bootloader enables it. When kexec kernel, ocotp clk needs to be enabled before reading ocotp registers, and nvmem API with platform driver supported can accomplish this. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alice Guo Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8m.c | 84 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index cc57a384d74d..071e14496e4b 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include #include @@ -29,7 +31,7 @@ struct imx8_soc_data { char *name; - u32 (*soc_revision)(void); + u32 (*soc_revision)(struct device *dev); }; static u64 soc_uid; @@ -50,7 +52,7 @@ static u32 imx8mq_soc_revision_from_atf(void) static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; #endif -static u32 __init imx8mq_soc_revision(void) +static u32 __init imx8mq_soc_revision(struct device *dev) { struct device_node *np; void __iomem *ocotp_base; @@ -75,9 +77,20 @@ static u32 __init imx8mq_soc_revision(void) rev = REV_B1; } - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + if (dev) { + int ret; + + ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid); + if (ret) { + iounmap(ocotp_base); + of_node_put(np); + return ret; + } + } else { + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + } iounmap(ocotp_base); of_node_put(np); @@ -107,7 +120,7 @@ static void __init imx8mm_soc_uid(void) of_node_put(np); } -static u32 __init imx8mm_soc_revision(void) +static u32 __init imx8mm_soc_revision(struct device *dev) { struct device_node *np; void __iomem *anatop_base; @@ -125,7 +138,15 @@ static u32 __init imx8mm_soc_revision(void) iounmap(anatop_base); of_node_put(np); - imx8mm_soc_uid(); + if (dev) { + int ret; + + ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid); + if (ret) + return ret; + } else { + imx8mm_soc_uid(); + } return rev; } @@ -150,7 +171,7 @@ static const struct imx8_soc_data imx8mp_soc_data = { .soc_revision = imx8mm_soc_revision, }; -static __maybe_unused const struct of_device_id imx8_soc_match[] = { +static __maybe_unused const struct of_device_id imx8_machine_match[] = { { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, }, { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, }, @@ -158,12 +179,20 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = { { } }; +static __maybe_unused const struct of_device_id imx8_soc_match[] = { + { .compatible = "fsl,imx8mq-soc", .data = &imx8mq_soc_data, }, + { .compatible = "fsl,imx8mm-soc", .data = &imx8mm_soc_data, }, + { .compatible = "fsl,imx8mn-soc", .data = &imx8mn_soc_data, }, + { .compatible = "fsl,imx8mp-soc", .data = &imx8mp_soc_data, }, + { } +}; + #define imx8_revision(soc_rev) \ soc_rev ? \ kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ "unknown" -static int __init imx8_soc_init(void) +static int imx8_soc_info(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; @@ -182,7 +211,10 @@ static int __init imx8_soc_init(void) if (ret) goto free_soc; - id = of_match_node(imx8_soc_match, of_root); + if (pdev) + id = of_match_node(imx8_soc_match, pdev->dev.of_node); + else + id = of_match_node(imx8_machine_match, of_root); if (!id) { ret = -ENODEV; goto free_soc; @@ -191,8 +223,16 @@ static int __init imx8_soc_init(void) data = id->data; if (data) { soc_dev_attr->soc_id = data->name; - if (data->soc_revision) - soc_rev = data->soc_revision(); + if (data->soc_revision) { + if (pdev) { + soc_rev = data->soc_revision(&pdev->dev); + ret = soc_rev; + if (ret < 0) + goto free_soc; + } else { + soc_rev = data->soc_revision(NULL); + } + } } soc_dev_attr->revision = imx8_revision(soc_rev); @@ -230,4 +270,24 @@ free_soc: kfree(soc_dev_attr); return ret; } + +/* Retain device_initcall is for backward compatibility with DTS. */ +static int __init imx8_soc_init(void) +{ + if (of_find_matching_node_and_match(NULL, imx8_soc_match, NULL)) + return 0; + + return imx8_soc_info(NULL); +} device_initcall(imx8_soc_init); + +static struct platform_driver imx8_soc_info_driver = { + .probe = imx8_soc_info, + .driver = { + .name = "imx8_soc_info", + .of_match_table = imx8_soc_match, + }, +}; + +module_platform_driver(imx8_soc_info_driver); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 82853543057f78d8a331272b70bc3f1e8cb0cbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 14 Dec 2020 19:07:42 +0100 Subject: dt-bindings: power: document Broadcom's PMB binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadcom's PMB is power controller used for disabling and enabling SoC devices. Signed-off-by: RafaÅ‚ MiÅ‚ecki Reviewed-by: Rob Herring Acked-by: Florian Fainelli Acked-by: Ulf Hansson Signed-off-by: Florian Fainelli --- .../devicetree/bindings/power/brcm,bcm-pmb.yaml | 50 ++++++++++++++++++++++ include/dt-bindings/soc/bcm-pmb.h | 11 +++++ 2 files changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/brcm,bcm-pmb.yaml create mode 100644 include/dt-bindings/soc/bcm-pmb.h diff --git a/Documentation/devicetree/bindings/power/brcm,bcm-pmb.yaml b/Documentation/devicetree/bindings/power/brcm,bcm-pmb.yaml new file mode 100644 index 000000000000..40b08d83c80b --- /dev/null +++ b/Documentation/devicetree/bindings/power/brcm,bcm-pmb.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/brcm,bcm-pmb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom PMB (Power Management Bus) controller + +description: This document describes Broadcom's PMB controller. It supports + powering various types of connected devices (e.g. PCIe, USB, SATA). + +maintainers: + - RafaÅ‚ MiÅ‚ecki + +properties: + compatible: + enum: + - brcm,bcm4908-pmb + + reg: + description: register space of one or more buses + maxItems: 1 + + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: Flag to use for block working in big endian mode. + + "#power-domain-cells": + description: cell specifies device ID (see bcm-pmb.h) + const: 1 + +required: + - reg + - "#power-domain-cells" + +additionalProperties: false + +examples: + - | + #include + + pmb: power-controller@802800e0 { + compatible = "brcm,bcm4908-pmb"; + reg = <0x802800e0 0x40>; + #power-domain-cells = <1>; + }; + + foo { + power-domains = <&pmb BCM_PMB_PCIE0>; + }; diff --git a/include/dt-bindings/soc/bcm-pmb.h b/include/dt-bindings/soc/bcm-pmb.h new file mode 100644 index 000000000000..744dc3af4d41 --- /dev/null +++ b/include/dt-bindings/soc/bcm-pmb.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT */ + +#ifndef __DT_BINDINGS_SOC_BCM_PMB_H +#define __DT_BINDINGS_SOC_BCM_PMB_H + +#define BCM_PMB_PCIE0 0x01 +#define BCM_PMB_PCIE1 0x02 +#define BCM_PMB_PCIE2 0x03 +#define BCM_PMB_HOST_USB 0x04 + +#endif -- cgit v1.2.3 From 8bcac4011ebe0dbdd46fd55b036ee855c95702d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 14 Dec 2020 19:07:43 +0100 Subject: soc: bcm: add PM driver for Broadcom's PMB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PMB originally comes from BCM63138 but can be also found on many other chipsets (e.g. BCM4908). It's needed to power on and off SoC blocks like PCIe, SATA, USB. Signed-off-by: RafaÅ‚ MiÅ‚ecki Acked-by: Ulf Hansson Signed-off-by: Florian Fainelli --- MAINTAINERS | 10 ++ drivers/soc/bcm/Makefile | 2 +- drivers/soc/bcm/bcm63xx/Kconfig | 9 ++ drivers/soc/bcm/bcm63xx/Makefile | 1 + drivers/soc/bcm/bcm63xx/bcm-pmb.c | 333 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/bcm/bcm63xx/bcm-pmb.c diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..3bbb974bd11e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3683,6 +3683,16 @@ L: linux-mips@vger.kernel.org S: Maintained F: drivers/firmware/broadcom/* +BROADCOM PMB (POWER MANAGEMENT BUS) DRIVER +M: RafaÅ‚ MiÅ‚ecki +M: Florian Fainelli +M: bcm-kernel-feedback-list@broadcom.com +L: linux-pm@vger.kernel.org +S: Maintained +T: git git://github.com/broadcom/stblinux.git +F: drivers/soc/bcm/bcm-pmb.c +F: include/dt-bindings/soc/bcm-pmb.h + BROADCOM SPECIFIC AMBA DRIVER (BCMA) M: RafaÅ‚ MiÅ‚ecki L: linux-wireless@vger.kernel.org diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile index 7bc90e0bd773..0f0efa28d92b 100644 --- a/drivers/soc/bcm/Makefile +++ b/drivers/soc/bcm/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o -obj-$(CONFIG_SOC_BCM63XX) += bcm63xx/ +obj-y += bcm63xx/ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig index 16f648a6c70a..9e501c8ac5ce 100644 --- a/drivers/soc/bcm/bcm63xx/Kconfig +++ b/drivers/soc/bcm/bcm63xx/Kconfig @@ -10,3 +10,12 @@ config BCM63XX_POWER BCM6318, BCM6328, BCM6362 and BCM63268 SoCs. endif # SOC_BCM63XX + +config BCM_PMB + bool "Broadcom PMB (Power Management Bus) driver" + depends on ARCH_BCM4908 || (COMPILE_TEST && OF) + default ARCH_BCM4908 + select PM_GENERIC_DOMAINS if PM + help + This enables support for the Broadcom's PMB (Power Management Bus) that + is used for disabling and enabling SoC devices. diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile index 0710d5e018cc..557eed3d67bd 100644 --- a/drivers/soc/bcm/bcm63xx/Makefile +++ b/drivers/soc/bcm/bcm63xx/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o +obj-$(CONFIG_BCM_PMB) += bcm-pmb.o diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c new file mode 100644 index 000000000000..c223023dc64f --- /dev/null +++ b/drivers/soc/bcm/bcm63xx/bcm-pmb.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2013 Broadcom + * Copyright (C) 2020 RafaÅ‚ MiÅ‚ecki + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BPCM_ID_REG 0x00 +#define BPCM_CAPABILITIES 0x04 +#define BPCM_CAP_NUM_ZONES 0x000000ff +#define BPCM_CAP_SR_REG_BITS 0x0000ff00 +#define BPCM_CAP_PLLTYPE 0x00030000 +#define BPCM_CAP_UBUS 0x00080000 +#define BPCM_CONTROL 0x08 +#define BPCM_STATUS 0x0c +#define BPCM_ROSC_CONTROL 0x10 +#define BPCM_ROSC_THRESH_H 0x14 +#define BPCM_ROSC_THRESHOLD_BCM6838 0x14 +#define BPCM_ROSC_THRESH_S 0x18 +#define BPCM_ROSC_COUNT_BCM6838 0x18 +#define BPCM_ROSC_COUNT 0x1c +#define BPCM_PWD_CONTROL_BCM6838 0x1c +#define BPCM_PWD_CONTROL 0x20 +#define BPCM_SR_CONTROL_BCM6838 0x20 +#define BPCM_PWD_ACCUM_CONTROL 0x24 +#define BPCM_SR_CONTROL 0x28 +#define BPCM_GLOBAL_CONTROL 0x2c +#define BPCM_MISC_CONTROL 0x30 +#define BPCM_MISC_CONTROL2 0x34 +#define BPCM_SGPHY_CNTL 0x38 +#define BPCM_SGPHY_STATUS 0x3c +#define BPCM_ZONE0 0x40 +#define BPCM_ZONE_CONTROL 0x00 +#define BPCM_ZONE_CONTROL_MANUAL_CLK_EN 0x00000001 +#define BPCM_ZONE_CONTROL_MANUAL_RESET_CTL 0x00000002 +#define BPCM_ZONE_CONTROL_FREQ_SCALE_USED 0x00000004 /* R/O */ +#define BPCM_ZONE_CONTROL_DPG_CAPABLE 0x00000008 /* R/O */ +#define BPCM_ZONE_CONTROL_MANUAL_MEM_PWR 0x00000030 +#define BPCM_ZONE_CONTROL_MANUAL_ISO_CTL 0x00000040 +#define BPCM_ZONE_CONTROL_MANUAL_CTL 0x00000080 +#define BPCM_ZONE_CONTROL_DPG_CTL_EN 0x00000100 +#define BPCM_ZONE_CONTROL_PWR_DN_REQ 0x00000200 +#define BPCM_ZONE_CONTROL_PWR_UP_REQ 0x00000400 +#define BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN 0x00000800 +#define BPCM_ZONE_CONTROL_BLK_RESET_ASSERT 0x00001000 +#define BPCM_ZONE_CONTROL_MEM_STBY 0x00002000 +#define BPCM_ZONE_CONTROL_RESERVED 0x0007c000 +#define BPCM_ZONE_CONTROL_PWR_CNTL_STATE 0x00f80000 +#define BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL 0x01000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_OFF_STATE 0x02000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_ON_STATE 0x04000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_GOOD 0x08000000 /* R/O */ +#define BPCM_ZONE_CONTROL_DPG_PWR_STATE 0x10000000 /* R/O */ +#define BPCM_ZONE_CONTROL_MEM_PWR_STATE 0x20000000 /* R/O */ +#define BPCM_ZONE_CONTROL_ISO_STATE 0x40000000 /* R/O */ +#define BPCM_ZONE_CONTROL_RESET_STATE 0x80000000 /* R/O */ +#define BPCM_ZONE_CONFIG1 0x04 +#define BPCM_ZONE_CONFIG2 0x08 +#define BPCM_ZONE_FREQ_SCALAR_CONTROL 0x0c +#define BPCM_ZONE_SIZE 0x10 + +struct bcm_pmb { + struct device *dev; + void __iomem *base; + spinlock_t lock; + bool little_endian; + struct genpd_onecell_data genpd_onecell_data; +}; + +struct bcm_pmb_pd_data { + const char * const name; + int id; + u8 bus; + u8 device; +}; + +struct bcm_pmb_pm_domain { + struct bcm_pmb *pmb; + const struct bcm_pmb_pd_data *data; + struct generic_pm_domain genpd; +}; + +static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device, + int offset, u32 *val) +{ + void __iomem *base = pmb->base + bus * 0x20; + unsigned long flags; + int err; + + spin_lock_irqsave(&pmb->lock, flags); + err = bpcm_rd(base, device, offset, val); + spin_unlock_irqrestore(&pmb->lock, flags); + + if (!err) + *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val); + + return err; +} + +static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device, + int offset, u32 val) +{ + void __iomem *base = pmb->base + bus * 0x20; + unsigned long flags; + int err; + + val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val); + + spin_lock_irqsave(&pmb->lock, flags); + err = bpcm_wr(base, device, offset, val); + spin_unlock_irqrestore(&pmb->lock, flags); + + return err; +} + +static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device, + int zone) +{ + int offset; + u32 val; + int err; + + offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + val |= BPCM_ZONE_CONTROL_PWR_DN_REQ; + val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + + return err; +} + +static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device, + int zone) +{ + int offset; + u32 val; + int err; + + offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) { + val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ; + val |= BPCM_ZONE_CONTROL_DPG_CTL_EN; + val |= BPCM_ZONE_CONTROL_PWR_UP_REQ; + val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN; + val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + } + + return err; +} + +static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device) +{ + int offset; + u32 val; + int err; + + /* Entire device can be powered off by powering off the 0th zone */ + offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) { + val = BPCM_ZONE_CONTROL_PWR_DN_REQ; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + } + + return err; +} + +static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device) +{ + u32 val; + int err; + int i; + + err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val); + if (err) + return err; + + for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) { + err = bcm_pmb_power_on_zone(pmb, bus, device, i); + if (err) + return err; + } + + return err; +} + +static int bcm_pmb_power_on(struct generic_pm_domain *genpd) +{ + struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); + const struct bcm_pmb_pd_data *data = pd->data; + struct bcm_pmb *pmb = pd->pmb; + + switch (data->id) { + case BCM_PMB_PCIE0: + case BCM_PMB_PCIE1: + case BCM_PMB_PCIE2: + return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0); + case BCM_PMB_HOST_USB: + return bcm_pmb_power_on_device(pmb, data->bus, data->device); + default: + dev_err(pmb->dev, "unsupported device id: %d\n", data->id); + return -EINVAL; + } +} + +static int bcm_pmb_power_off(struct generic_pm_domain *genpd) +{ + struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); + const struct bcm_pmb_pd_data *data = pd->data; + struct bcm_pmb *pmb = pd->pmb; + + switch (data->id) { + case BCM_PMB_PCIE0: + case BCM_PMB_PCIE1: + case BCM_PMB_PCIE2: + return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0); + case BCM_PMB_HOST_USB: + return bcm_pmb_power_off_device(pmb, data->bus, data->device); + default: + dev_err(pmb->dev, "unsupported device id: %d\n", data->id); + return -EINVAL; + } +} + +static int bcm_pmb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct bcm_pmb_pd_data *table; + const struct bcm_pmb_pd_data *e; + struct resource *res; + struct bcm_pmb *pmb; + int max_id; + int err; + + pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL); + if (!pmb) + return -ENOMEM; + + pmb->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pmb->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pmb->base)) + return PTR_ERR(pmb->base); + + spin_lock_init(&pmb->lock); + + pmb->little_endian = !of_device_is_big_endian(dev->of_node); + + table = of_device_get_match_data(dev); + if (!table) + return -EINVAL; + + max_id = 0; + for (e = table; e->name; e++) + max_id = max(max_id, e->id); + + pmb->genpd_onecell_data.num_domains = max_id + 1; + pmb->genpd_onecell_data.domains = + devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains, + sizeof(struct generic_pm_domain *), GFP_KERNEL); + if (!pmb->genpd_onecell_data.domains) + return -ENOMEM; + + for (e = table; e->name; e++) { + struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + + pd->pmb = pmb; + pd->data = e; + pd->genpd.name = e->name; + pd->genpd.power_on = bcm_pmb_power_on; + pd->genpd.power_off = bcm_pmb_power_off; + + pm_genpd_init(&pd->genpd, NULL, true); + pmb->genpd_onecell_data.domains[e->id] = &pd->genpd; + } + + err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data); + if (err) { + dev_err(dev, "failed to add genpd provider: %d\n", err); + return err; + } + + return 0; +} + +static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = { + { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, }, + { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, }, + { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, }, + { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, }, + { }, +}; + +static const struct of_device_id bcm_pmb_of_match[] = { + { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, }, + { }, +}; + +static struct platform_driver bcm_pmb_driver = { + .driver = { + .name = "bcm-pmb", + .of_match_table = bcm_pmb_of_match, + }, + .probe = bcm_pmb_probe, +}; + +builtin_platform_driver(bcm_pmb_driver); -- cgit v1.2.3 From a90b6543bf062d65292b2c76f1630507d1c9d8ec Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Tue, 12 Jan 2021 19:13:26 +0000 Subject: firmware: arm_scmi: Fix call site of scmi_notification_exit Call scmi_notification_exit() only when SCMI platform driver instance has been really successfully removed. Link: https://lore.kernel.org/r/20210112191326.29091-1-cristian.marussi@arm.com Fixes: 6b8a69131dc63 ("firmware: arm_scmi: Enable notification core") Signed-off-by: Cristian Marussi [sudeep.holla: Move the call outside the list mutex locking] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 5392e1fc6b4e..cacdf1589b10 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -848,8 +848,6 @@ static int scmi_remove(struct platform_device *pdev) struct scmi_info *info = platform_get_drvdata(pdev); struct idr *idr = &info->tx_idr; - scmi_notification_exit(&info->handle); - mutex_lock(&scmi_list_mutex); if (info->users) ret = -EBUSY; @@ -860,6 +858,8 @@ static int scmi_remove(struct platform_device *pdev) if (ret) return ret; + scmi_notification_exit(&info->handle); + /* Safe to free channels since no more users */ ret = idr_for_each(idr, info->desc->ops->chan_free, idr); idr_destroy(&info->tx_idr); -- cgit v1.2.3 From ac9b7554afeb455a74bd69dc4a8eecf49886ff48 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 Jan 2021 09:04:50 +0100 Subject: reset: core: fix a kernel-doc markup A function has a different name between their prototype and its kernel-doc markup: ../drivers/reset/core.c:888: warning: expecting prototype for device_reset(). Prototype was for __device_reset() instead Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 34e89aa0fb5e..dbf881b586d9 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -875,8 +875,8 @@ struct reset_control *__devm_reset_control_get(struct device *dev, EXPORT_SYMBOL_GPL(__devm_reset_control_get); /** - * device_reset - find reset controller associated with the device - * and perform reset + * __device_reset - find reset controller associated with the device + * and perform reset * @dev: device to be reset by the controller * @optional: whether it is optional to reset the device * -- cgit v1.2.3 From 3c15e00e7b58bc2b37e53d2612f0a0163281be77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 26 Nov 2020 11:41:42 +0100 Subject: mfd/bus: sunxi-rsb: Make .remove() callback return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver core ignores the return value of struct device_driver::remove because there is only little that can be done. To simplify the quest to make this function return void, let struct sunxi_rsb_driver::remove return void, too. All users already unconditionally return 0, this commit makes this obvious and ensures future users don't behave differently. To simplify even further, make axp20x_device_remove() return void instead of returning 0 unconditionally, too. Signed-off-by: Uwe Kleine-König Reviewed-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/bus/sunxi-rsb.c | 4 +++- drivers/mfd/axp20x-i2c.c | 4 +++- drivers/mfd/axp20x-rsb.c | 4 ++-- drivers/mfd/axp20x.c | 4 +--- include/linux/mfd/axp20x.h | 2 +- include/linux/sunxi-rsb.h | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 1bb00a959c67..117716e23ffb 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -170,7 +170,9 @@ static int sunxi_rsb_device_remove(struct device *dev) { const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver); - return drv->remove(to_sunxi_rsb_device(dev)); + drv->remove(to_sunxi_rsb_device(dev)); + + return 0; } static struct bus_type sunxi_rsb_bus = { diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index 2cfde81f5fbf..00ab48018d8d 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -54,7 +54,9 @@ static int axp20x_i2c_remove(struct i2c_client *i2c) { struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); - return axp20x_device_remove(axp20x); + axp20x_device_remove(axp20x); + + return 0; } #ifdef CONFIG_OF diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 4cdc79f5cc48..214bc0d84d44 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c @@ -49,11 +49,11 @@ static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev) return axp20x_device_probe(axp20x); } -static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) +static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev) { struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev); - return axp20x_device_remove(axp20x); + axp20x_device_remove(axp20x); } static const struct of_device_id axp20x_rsb_of_match[] = { diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index aa59496e4376..3eae04e24ac8 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -987,7 +987,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) } EXPORT_SYMBOL(axp20x_device_probe); -int axp20x_device_remove(struct axp20x_dev *axp20x) +void axp20x_device_remove(struct axp20x_dev *axp20x) { if (axp20x == axp20x_pm_power_off) { axp20x_pm_power_off = NULL; @@ -996,8 +996,6 @@ int axp20x_device_remove(struct axp20x_dev *axp20x) mfd_remove_devices(axp20x->dev); regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); - - return 0; } EXPORT_SYMBOL(axp20x_device_remove); diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index fd5957c042da..9ab0e2fca7ea 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -696,6 +696,6 @@ int axp20x_device_probe(struct axp20x_dev *axp20x); * * This tells the axp20x core to remove the associated mfd devices */ -int axp20x_device_remove(struct axp20x_dev *axp20x); +void axp20x_device_remove(struct axp20x_dev *axp20x); #endif /* __LINUX_MFD_AXP20X_H */ diff --git a/include/linux/sunxi-rsb.h b/include/linux/sunxi-rsb.h index 7e75bb0346d0..bf0d365f471c 100644 --- a/include/linux/sunxi-rsb.h +++ b/include/linux/sunxi-rsb.h @@ -59,7 +59,7 @@ static inline void sunxi_rsb_device_set_drvdata(struct sunxi_rsb_device *rdev, struct sunxi_rsb_driver { struct device_driver driver; int (*probe)(struct sunxi_rsb_device *rdev); - int (*remove)(struct sunxi_rsb_device *rdev); + void (*remove)(struct sunxi_rsb_device *rdev); }; static inline struct sunxi_rsb_driver *to_sunxi_rsb_driver(struct device_driver *d) -- cgit v1.2.3 From 0c0d0e56e08ca3ae5f4a8922b6575bdf48b79974 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Dec 2020 16:04:46 +0300 Subject: soc: qcom: socinfo: add qrb5165 SoC ID Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201222130448.4125297-1-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index d21530d24253..d4b0d6539df4 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -234,6 +234,7 @@ static const struct soc_id soc_id[] = { { 356, "SM8250" }, { 402, "IPQ6018" }, { 425, "SC7180" }, + { 455, "QRB5165" }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) -- cgit v1.2.3 From 4305324208d8da4b4ce0efb20af9745effda3a2e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Dec 2020 16:04:47 +0300 Subject: soc: qcom: socinfo: add several PMIC IDs Add several PMIC IDs found on Qualcomm RB5 platform. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201222130448.4125297-2-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index d4b0d6539df4..5536f1dd1d07 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -83,6 +83,11 @@ static const char *const pmic_models[] = { [23] = "PM8038", [24] = "PM8922", [25] = "PM8917", + [30] = "PM8150", + [31] = "PM8150L", + [32] = "PM8150B", + [33] = "PMK8002", + [36] = "PM8009", }; #endif /* CONFIG_DEBUG_FS */ -- cgit v1.2.3 From 734c78e7febf879a79e9b34e38df35cc63794350 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Dec 2020 16:04:48 +0300 Subject: soc: qcom: socinfo: add info from PMIC models array Add debugfs file showing information from PMIC model array. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201222130448.4125297-3-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 5536f1dd1d07..f5c190ceb667 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -15,6 +15,8 @@ #include #include +#include + /* * SoC version type with major number in the upper 16 bits and minor * number in the lower 16 bits. @@ -300,6 +302,32 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p) return 0; } +static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) +{ + struct socinfo *socinfo = seq->private; + unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics); + unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset); + int i; + void *ptr = socinfo; + + ptr += pmic_array_offset; + + /* No need for bounds checking, it happened at socinfo_debugfs_init */ + for (i = 0; i < num_pmics; i++) { + unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32))); + unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32)); + + if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model]) + seq_printf(seq, "%s %u.%u\n", pmic_models[model], + SOCINFO_MAJOR(le32_to_cpu(die_rev)), + SOCINFO_MINOR(le32_to_cpu(die_rev))); + else + seq_printf(seq, "unknown (%d)\n", model); + } + + return 0; +} + static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p) { struct socinfo *socinfo = seq->private; @@ -322,6 +350,7 @@ static int qcom_show_chip_id(struct seq_file *seq, void *p) QCOM_OPEN(build_id, qcom_show_build_id); QCOM_OPEN(pmic_model, qcom_show_pmic_model); +QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array); QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); QCOM_OPEN(chip_id, qcom_show_chip_id); @@ -350,12 +379,14 @@ DEFINE_IMAGE_OPS(variant); DEFINE_IMAGE_OPS(oem); static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info) + struct socinfo *info, size_t info_size) { struct smem_image_version *versions; struct dentry *dentry; size_t size; int i; + unsigned int num_pmics; + unsigned int pmic_array_offset; qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL); @@ -411,6 +442,11 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.raw_device_num); fallthrough; case SOCINFO_VERSION(0, 11): + num_pmics = le32_to_cpu(info->num_pmics); + pmic_array_offset = le32_to_cpu(info->pmic_array_offset); + if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size) + DEBUGFS_ADD(info, pmic_model_array); + fallthrough; case SOCINFO_VERSION(0, 10): case SOCINFO_VERSION(0, 9): qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id); @@ -488,7 +524,7 @@ static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) } #else static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info) + struct socinfo *info, size_t info_size) { } static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { } @@ -528,7 +564,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev) if (IS_ERR(qs->soc_dev)) return PTR_ERR(qs->soc_dev); - socinfo_debugfs_init(qs, info); + socinfo_debugfs_init(qs, info, item_size); /* Feed the soc specific unique data into entropy pool */ add_device_randomness(info, item_size); -- cgit v1.2.3 From 8333b2c26c2f38ed9510bce40e5a5c88d46c961e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 15 Dec 2020 23:19:26 -0800 Subject: soc: qcom: socinfo: Open read access to all for debugfs There doesn't seem to be any reason to limit this to only root user readable. Let's make it readable by all so that random programs can read the debugfs files in here instead of just root. The information is just that, informational, so this is fine. Reviewed-by: Sai Prakash Ranjan Reviewed-by: Douglas Anderson Cc: Sai Prakash Ranjan Cc: Douglas Anderson Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20201216071926.3147108-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index f5c190ceb667..c35e4c651602 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -272,7 +272,7 @@ static const struct file_operations qcom_ ##name## _ops = { \ } #define DEBUGFS_ADD(info, name) \ - debugfs_create_file(__stringify(name), 0400, \ + debugfs_create_file(__stringify(name), 0444, \ qcom_socinfo->dbg_root, \ info, &qcom_ ##name## _ops) @@ -392,14 +392,14 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt); - debugfs_create_x32("info_fmt", 0400, qcom_socinfo->dbg_root, + debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { case SOCINFO_VERSION(0, 15): qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported); - debugfs_create_u32("nmodem_supported", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.nmodem_supported); fallthrough; case SOCINFO_VERSION(0, 14): @@ -408,19 +408,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts); qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset); - debugfs_create_u32("num_clusters", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_clusters); - debugfs_create_u32("ncluster_array_offset", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_defective_parts", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_defective_parts); - debugfs_create_u32("ndefective_parts_array_offset", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ndefective_parts_array_offset); fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); - debugfs_create_u32("nproduct_id", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.nproduct_id); DEBUGFS_ADD(info, chip_id); fallthrough; @@ -432,12 +432,12 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.raw_device_num = __le32_to_cpu(info->raw_device_num); - debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root, + debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.chip_family); - debugfs_create_x32("raw_device_family", 0400, + debugfs_create_x32("raw_device_family", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_family); - debugfs_create_x32("raw_device_number", 0400, + debugfs_create_x32("raw_device_number", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_num); fallthrough; @@ -451,7 +451,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, case SOCINFO_VERSION(0, 9): qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id); - debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.foundry_id); fallthrough; case SOCINFO_VERSION(0, 8): @@ -463,7 +463,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.hw_plat_subtype = __le32_to_cpu(info->hw_plat_subtype); - debugfs_create_u32("hardware_platform_subtype", 0400, + debugfs_create_u32("hardware_platform_subtype", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat_subtype); fallthrough; @@ -471,28 +471,28 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.accessory_chip = __le32_to_cpu(info->accessory_chip); - debugfs_create_u32("accessory_chip", 0400, + debugfs_create_u32("accessory_chip", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.accessory_chip); fallthrough; case SOCINFO_VERSION(0, 4): qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); - debugfs_create_u32("platform_version", 0400, + debugfs_create_u32("platform_version", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.plat_ver); fallthrough; case SOCINFO_VERSION(0, 3): qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); - debugfs_create_u32("hardware_platform", 0400, + debugfs_create_u32("hardware_platform", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat); fallthrough; case SOCINFO_VERSION(0, 2): qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); - debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_ver); fallthrough; case SOCINFO_VERSION(0, 1): @@ -509,11 +509,11 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, dentry = debugfs_create_dir(socinfo_image_names[i], qcom_socinfo->dbg_root); - debugfs_create_file("name", 0400, dentry, &versions[i], + debugfs_create_file("name", 0444, dentry, &versions[i], &qcom_image_name_ops); - debugfs_create_file("variant", 0400, dentry, &versions[i], + debugfs_create_file("variant", 0444, dentry, &versions[i], &qcom_image_variant_ops); - debugfs_create_file("oem", 0400, dentry, &versions[i], + debugfs_create_file("oem", 0444, dentry, &versions[i], &qcom_image_oem_ops); } } -- cgit v1.2.3 From 0da78ae2e04c56f8f7ad9a28abdb5131b1bdf013 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 9 Jan 2021 17:31:22 +0100 Subject: soc: qcom: socinfo: Add SoC IDs for 630 family Add missing SoC IDs for Snapdragon 630-family platforms. Signed-off-by: Konrad Dybcio Tested-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20210109163123.147185-1-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c35e4c651602..3b1afd3f3b16 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -231,10 +231,17 @@ static const struct soc_id soc_id[] = { { 310, "MSM8996AU" }, { 311, "APQ8096AU" }, { 312, "APQ8096SG" }, + { 317, "SDM660" }, { 318, "SDM630" }, { 321, "SDM845" }, + { 324, "SDA660" }, + { 325, "SDM658" }, + { 326, "SDA658" }, + { 327, "SDA630" }, { 338, "SDM450" }, { 341, "SDA845" }, + { 345, "SDM636" }, + { 346, "SDA636" }, { 349, "SDM632" }, { 350, "SDA632" }, { 351, "SDA450" }, -- cgit v1.2.3 From 407bdcf9beb3e96cca26abeec38955f4c320fa3d Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 9 Jan 2021 17:31:23 +0100 Subject: soc: qcom: socinfo: Add SoC IDs for APQ/MSM8998 Add missing SoC IDs for Snapdragon 835-family platforms. Signed-off-by: Konrad Dybcio Tested-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20210109163123.147185-2-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 3b1afd3f3b16..bcf621e1db30 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -225,6 +225,7 @@ static const struct soc_id soc_id[] = { { 251, "MSM8992" }, { 253, "APQ8094" }, { 291, "APQ8096" }, + { 292, "MSM8998" }, { 293, "MSM8953" }, { 304, "APQ8053" }, { 305, "MSM8996SG" }, @@ -233,6 +234,7 @@ static const struct soc_id soc_id[] = { { 312, "APQ8096SG" }, { 317, "SDM660" }, { 318, "SDM630" }, + { 319, "APQ8098" }, { 321, "SDM845" }, { 324, "SDA660" }, { 325, "SDM658" }, -- cgit v1.2.3 From 3bc4bf77fa2adca8d6677461b6ec57505f1a3331 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 15 Jan 2021 17:27:28 +0100 Subject: soc: qcom: socinfo: Add MDM9607 IDs Along with IDs for its derivatives. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210115162728.118249-1-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index bcf621e1db30..a985ed064669 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -224,9 +224,14 @@ static const struct soc_id soc_id[] = { { 250, "MSM8616" }, { 251, "MSM8992" }, { 253, "APQ8094" }, + { 290, "MDM9607" }, { 291, "APQ8096" }, { 292, "MSM8998" }, { 293, "MSM8953" }, + { 296, "MDM8207" }, + { 297, "MDM9207" }, + { 298, "MDM9307" }, + { 299, "MDM9628" }, { 304, "APQ8053" }, { 305, "MSM8996SG" }, { 310, "MSM8996AU" }, @@ -236,6 +241,7 @@ static const struct soc_id soc_id[] = { { 318, "SDM630" }, { 319, "APQ8098" }, { 321, "SDM845" }, + { 322, "MDM9206" }, { 324, "SDA660" }, { 325, "SDM658" }, { 326, "SDA658" }, -- cgit v1.2.3 From 149ae80b1d50e7db5ac7df1cdf0820017b70e716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Jan 2021 11:53:18 +0100 Subject: soc: bcm: brcmstb: add stubs for getting platform IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some brcmstb drivers may be shared with other SoC families. E.g. the same USB PHY block is shared by brcmstb and BCM4908. To avoid building brcmstb common code on non-brcmstb platforms we need stubs for: 1. brcmstb_get_family_id() 2. brcmstb_get_product_id() (to avoid "undefined reference to" errors). With this change PHY_BRCM_USB will not have to unconditionally select SOC_BRCMSTB anymore. Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: Florian Fainelli --- include/linux/soc/brcmstb/brcmstb.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/soc/brcmstb/brcmstb.h b/include/linux/soc/brcmstb/brcmstb.h index 8e884e0dda0a..f2b768852777 100644 --- a/include/linux/soc/brcmstb/brcmstb.h +++ b/include/linux/soc/brcmstb/brcmstb.h @@ -2,6 +2,8 @@ #ifndef __BRCMSTB_SOC_H #define __BRCMSTB_SOC_H +#include + static inline u32 BRCM_ID(u32 reg) { return reg >> 28 ? reg >> 16 : reg >> 8; @@ -12,6 +14,8 @@ static inline u32 BRCM_REV(u32 reg) return reg & 0xff; } +#if IS_ENABLED(CONFIG_SOC_BRCMSTB) + /* * Helper functions for getting family or product id from the * SoC driver. @@ -19,4 +23,16 @@ static inline u32 BRCM_REV(u32 reg) u32 brcmstb_get_family_id(void); u32 brcmstb_get_product_id(void); +#else +static inline u32 brcmstb_get_family_id(void) +{ + return 0; +} + +static inline u32 brcmstb_get_product_id(void) +{ + return 0; +} +#endif + #endif /* __BRCMSTB_SOC_H */ -- cgit v1.2.3 From e6393818c8d13cb602af4850bcef47ead1455bbf Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 18 Jan 2021 11:36:51 +0000 Subject: soc: qcom: socinfo: Fix off-by-one array index bounds check There is an off-by-one array index bounds check on array pmic_models. Fix this by checking using < rather than <= on the array size. Addresses-Coverity: ("Out-of-bounds read") Fixes: 734c78e7febf ("soc: qcom: socinfo: add info from PMIC models array") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210118113651.71955-1-colin.king@canonical.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index a985ed064669..f449df560d93 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -332,7 +332,7 @@ static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32))); unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32)); - if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model]) + if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) seq_printf(seq, "%s %u.%u\n", pmic_models[model], SOCINFO_MAJOR(le32_to_cpu(die_rev)), SOCINFO_MINOR(le32_to_cpu(die_rev))); -- cgit v1.2.3 From 5fb33d8960dc7abdabc6fe599a30c2c99b082ef6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 20 Jan 2021 12:57:55 +0300 Subject: soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model() These need to be < ARRAY_SIZE() instead of <= ARRAY_SIZE() to prevent accessing one element beyond the end of the array. Acked-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Reviewed-by: Stephen Boyd Fixes: e9247e2ce577 ("soc: qcom: socinfo: fix printing of pmic_model") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/YAf+o85Z9lgkq3Nw@mwanda Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index f449df560d93..5b4ad24a022b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -309,7 +309,7 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p) if (model < 0) return -EINVAL; - if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model]) + if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) seq_printf(seq, "%s\n", pmic_models[model]); else seq_printf(seq, "unknown (%d)\n", model); -- cgit v1.2.3 From 1821203150330c4b5604b0350f23902838b53fb7 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Thu, 21 Jan 2021 14:24:27 +0800 Subject: memory: mtk-smi: Use platform_register_drivers In this file, we have 2 drivers, smi-common and smi-larb. Use platform_register_drivers. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210121062429.26504-2-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 82d09b88240e..c07bb0b3144b 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -587,26 +587,13 @@ static struct platform_driver mtk_smi_common_driver = { } }; +static struct platform_driver * const smidrivers[] = { + &mtk_smi_common_driver, + &mtk_smi_larb_driver, +}; + static int __init mtk_smi_init(void) { - int ret; - - ret = platform_driver_register(&mtk_smi_common_driver); - if (ret != 0) { - pr_err("Failed to register SMI driver\n"); - return ret; - } - - ret = platform_driver_register(&mtk_smi_larb_driver); - if (ret != 0) { - pr_err("Failed to register SMI-LARB driver\n"); - goto err_unreg_smi; - } - return ret; - -err_unreg_smi: - platform_driver_unregister(&mtk_smi_common_driver); - return ret; + return platform_register_drivers(smidrivers, ARRAY_SIZE(smidrivers)); } - module_init(mtk_smi_init); -- cgit v1.2.3 From 6ce84ab6492c8634039267d1d9e89fe41dcd4770 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 02:52:10 +0300 Subject: memory: tegra: Check whether reset is already asserted Check whether memory client reset is already asserted in order to prevent DMA-flush error on trying to re-assert an already asserted reset. This becomes a problem once PMC GENPD is enabled to use memory resets since GENPD will get a error and fail to toggle power domain. PMC GENPDs can't be toggled safely without holding memory reset on Tegra and we're about to fix this. Tested-by: Peter Geis # Ouya T30 Tested-by: Nicolas Chauvet # PAZ00 T20 Tested-by: Matt Merhar # Ouya T30 Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210119235210.13006-1-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 44064de962c2..a21163ccadc4 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -176,6 +176,13 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev, if (!rst_ops) return -ENODEV; + /* DMA flushing will fail if reset is already asserted */ + if (rst_ops->reset_status) { + /* check whether reset is asserted */ + if (rst_ops->reset_status(mc, rst)) + return 0; + } + if (rst_ops->block_dma) { /* block clients DMA requests */ err = rst_ops->block_dma(mc, rst); -- cgit v1.2.3 From a88f66d4a8668e66afa8eb4099b4515e0729b52a Mon Sep 17 00:00:00 2001 From: Vasyl Gomonovych Date: Sun, 24 Jan 2021 20:51:36 -0800 Subject: soc: ti: knav_qmss: Put refcount for dev node in failure case for_each_child_of_node increases refcount for each device_node and decreases previous one in a loop, but in case jump out of a loop current node refcount has no chnase for decreases so requires an of_node_put for jupm out cases. Fix based on raport from scripts/coccinelle/iterators/for_each_child.cocci Signed-off-by: Vasyl Gomonovych Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/knav_dma.c | 1 + drivers/soc/ti/knav_qmss_queue.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 7b5cb5d48f7d..591d14ebcb11 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -758,6 +758,7 @@ static int knav_dma_probe(struct platform_device *pdev) for_each_child_of_node(node, child) { ret = dma_init(node, child); if (ret) { + of_node_put(child); dev_err(&pdev->dev, "init failed with %d\n", ret); break; } diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 2e521f1eda96..2ac3856b8d42 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -1087,6 +1087,7 @@ static int knav_queue_setup_regions(struct knav_device *kdev, for_each_child_of_node(regions, child) { region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); if (!region) { + of_node_put(child); dev_err(dev, "out of memory allocating region\n"); return -ENOMEM; } @@ -1399,6 +1400,7 @@ static int knav_queue_init_qmgrs(struct knav_device *kdev, for_each_child_of_node(qmgrs, child) { qmgr = devm_kzalloc(dev, sizeof(*qmgr), GFP_KERNEL); if (!qmgr) { + of_node_put(child); dev_err(dev, "out of memory allocating qmgr\n"); return -ENOMEM; } @@ -1498,6 +1500,7 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, for_each_child_of_node(pdsps, child) { pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); if (!pdsp) { + of_node_put(child); dev_err(dev, "out of memory allocating pdsp\n"); return -ENOMEM; } -- cgit v1.2.3 From 17ad4662595ea0c4fd7496b664523ef632e63349 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 24 Jan 2021 20:51:36 -0800 Subject: soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function 'am33xx_pm_rtc_setup()' allocates some resources that must be freed on the error. Commit 2152fbbd47c0 ("soc: ti: pm33xx: Simplify RTC usage to prepare to drop platform data") has introduced the use of these resources but has only updated the remove function. Fix the error handling path of the probe function now. Fixes: 2152fbbd47c0 ("soc: ti: pm33xx: Simplify RTC usage to prepare to drop platform data") Signed-off-by: Christophe JAILLET Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pm33xx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index 64f3e3105540..7bab4bbaf02d 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -535,7 +535,7 @@ static int am33xx_pm_probe(struct platform_device *pdev) ret = am33xx_push_sram_idle(); if (ret) - goto err_free_sram; + goto err_unsetup_rtc; am33xx_pm_set_ipc_ops(); @@ -575,6 +575,9 @@ err_pm_runtime_put: err_pm_runtime_disable: pm_runtime_disable(dev); wkup_m3_ipc_put(m3_ipc); +err_unsetup_rtc: + iounmap(rtc_base_virt); + clk_put(rtc_fck); err_free_sram: am33xx_pm_free_sram(); pm33xx_dev = NULL; -- cgit v1.2.3 From f97a8a34353e993f7dc2c204faaa033955907bdc Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 24 Jan 2021 20:51:37 -0800 Subject: soc: ti: pruss: Correct the pruss_clk_init error trace text The pruss_clk_init() function can register more than one clock. Correct the existing misleading error trace upon a failure within this function. Signed-off-by: Suman Anna Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 5d6e7132a5c4..1d6890134312 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -273,7 +273,7 @@ static int pruss_probe(struct platform_device *pdev) ret = pruss_clk_init(pruss, child); if (ret) { - dev_err(dev, "failed to setup coreclk-mux\n"); + dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret); goto node_put; } -- cgit v1.2.3 From 822be879980d8a2ddcb7268c77c682c0cdd3c086 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Sun, 24 Jan 2021 20:51:37 -0800 Subject: dt-bindings: soc: ti: Update TI PRUSS bindings about schemas to include Now after ti,pruss-intc.yaml and ti,pru-rproc.yaml are merged, include them in proper property and extend the examples section. At the occasion extend the allowed property list about dma-ranges. Reviewed-by: Rob Herring Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/soc/ti/ti,pruss.yaml | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml index 037c51b2f972..dbc62821c60b 100644 --- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -81,6 +81,9 @@ properties: ranges: maxItems: 1 + dma-ranges: + maxItems: 1 + power-domains: description: | This property is as per sci-pm-domain.txt. @@ -278,6 +281,9 @@ patternProperties: that is common to all the PRU cores. This should be represented as an interrupt-controller node. + allOf: + - $ref: /schemas/interrupt-controller/ti,pruss-intc.yaml# + type: object mdio@[a-f0-9]+$: @@ -299,6 +305,9 @@ patternProperties: present on K3 SoCs have additional auxiliary PRU cores with slightly different IP integration. + allOf: + - $ref: /schemas/remoteproc/ti,pru-rproc.yaml# + type: object required: @@ -371,6 +380,36 @@ examples: reg = <0x32000 0x58>; }; + pruss_intc: interrupt-controller@20000 { + compatible = "ti,pruss-intc"; + reg = <0x20000 0x2000>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <20 21 22 23 24 25 26 27>; + interrupt-names = "host_intr0", "host_intr1", + "host_intr2", "host_intr3", + "host_intr4", "host_intr5", + "host_intr6", "host_intr7"; + }; + + pru0: pru@34000 { + compatible = "ti,am3356-pru"; + reg = <0x34000 0x2000>, + <0x22000 0x400>, + <0x22400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am335x-pru0-fw"; + }; + + pru1: pru@38000 { + compatible = "ti,am3356-pru"; + reg = <0x38000 0x2000>, + <0x24000 0x400>, + <0x24400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am335x-pru1-fw"; + }; + pruss_mdio: mdio@32400 { compatible = "ti,davinci_mdio"; reg = <0x32400 0x90>; @@ -425,6 +464,43 @@ examples: reg = <0x32000 0x58>; }; + pruss1_intc: interrupt-controller@20000 { + compatible = "ti,pruss-intc"; + reg = <0x20000 0x2000>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "host_intr0", "host_intr1", + "host_intr2", "host_intr3", + "host_intr4", + "host_intr6", "host_intr7"; + ti,irqs-reserved = /bits/ 8 <0x20>; /* BIT(5) */ + }; + + pru1_0: pru@34000 { + compatible = "ti,am4376-pru"; + reg = <0x34000 0x3000>, + <0x22000 0x400>, + <0x22400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am437x-pru1_0-fw"; + }; + + pru1_1: pru@38000 { + compatible = "ti,am4376-pru"; + reg = <0x38000 0x3000>, + <0x24000 0x400>, + <0x24400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am437x-pru1_1-fw"; + }; + pruss1_mdio: mdio@32400 { compatible = "ti,davinci_mdio"; reg = <0x32400 0x90>; -- cgit v1.2.3 From d17655759b3fc660ea49bd7be665c193030c77c0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sat, 23 Jan 2021 19:34:45 +0300 Subject: reset: Add devm_reset_control_get_optional_exclusive_released() NVIDIA Tegra DRM and media drivers will need a resource-managed-optional variant of reset_control_get_exclusive_released() in order to switch away from a legacy Tegra-specific PD API to a GENPD API without much hassle. Add the new reset helper to the reset API. Tested-by: Peter Geis # Ouya T30 Tested-by: Nicolas Chauvet # PAZ00 T20 Tested-by: Matt Merhar # Ouya T30 Signed-off-by: Dmitry Osipenko Signed-off-by: Philipp Zabel --- include/linux/reset.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/linux/reset.h b/include/linux/reset.h index 439fec7112a9..b9109efa2a5c 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -362,6 +362,25 @@ __must_check devm_reset_control_get_exclusive_released(struct device *dev, return __devm_reset_control_get(dev, id, 0, false, false, false); } +/** + * devm_reset_control_get_optional_exclusive_released - resource managed + * reset_control_get_optional_exclusive_released() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed-and-optional variant of reset_control_get_exclusive_released(). For + * reset controllers returned from this function, reset_control_put() is called + * automatically on driver detach. + * + * See reset_control_get_exclusive_released() for more information. + */ +static inline struct reset_control * +__must_check devm_reset_control_get_optional_exclusive_released(struct device *dev, + const char *id) +{ + return __devm_reset_control_get(dev, id, 0, false, true, false); +} + /** * devm_reset_control_get_shared - resource managed reset_control_get_shared() * @dev: device to be reset by the controller -- cgit v1.2.3 From 43eb76a2e56b94541293fc8192d6edf1d0ec8965 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 18 Jan 2021 17:19:41 +0100 Subject: drivers: soc: qcom: rpmpd: Add msm8994 RPM Power Domains MSM8994 uses similar to MSM8996, legacy-style voltage control, but does not include a VDD_SC_CX line. This setup is also correct for MSM8992. Do note that there exist some boards that use a tertiary PMIC (most likely pm8004), where SMPB on VDDGFX becomes SMPC. I cannot test this configuration though. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210118161943.105733-1-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/power/qcom,rpmpd.yaml | 1 + drivers/soc/qcom/rpmpd.c | 28 ++++++++++++++++++++++ include/dt-bindings/power/qcom-rpmpd.h | 9 +++++++ 3 files changed, 38 insertions(+) diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml index 64825128ee97..1ea21acbbd55 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml @@ -19,6 +19,7 @@ properties: - qcom,msm8916-rpmpd - qcom,msm8939-rpmpd - qcom,msm8976-rpmpd + - qcom,msm8994-rpmpd - qcom,msm8996-rpmpd - qcom,msm8998-rpmpd - qcom,qcs404-rpmpd diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 85d1207b72d7..27733b0e7fca 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -21,6 +21,8 @@ * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ #define RPMPD_SMPA 0x61706d73 #define RPMPD_LDOA 0x616f646c +#define RPMPD_SMPB 0x62706d73 +#define RPMPD_LDOB 0x626f646c #define RPMPD_RWCX 0x78637772 #define RPMPD_RWMX 0x786d7772 #define RPMPD_RWLC 0x636c7772 @@ -184,6 +186,31 @@ static const struct rpmpd_desc msm8976_desc = { .max_state = RPM_SMD_LEVEL_TURBO_HIGH, }; +/* msm8994 RPM Power domains */ +DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1); +DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2); +/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */ +DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2); + +DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1); +DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2); + +static struct rpmpd *msm8994_rpmpds[] = { + [MSM8994_VDDCX] = &msm8994_vddcx, + [MSM8994_VDDCX_AO] = &msm8994_vddcx_ao, + [MSM8994_VDDCX_VFC] = &msm8994_vddcx_vfc, + [MSM8994_VDDMX] = &msm8994_vddmx, + [MSM8994_VDDMX_AO] = &msm8994_vddmx_ao, + [MSM8994_VDDGFX] = &msm8994_vddgfx, + [MSM8994_VDDGFX_VFC] = &msm8994_vddgfx_vfc, +}; + +static const struct rpmpd_desc msm8994_desc = { + .rpmpds = msm8994_rpmpds, + .num_pds = ARRAY_SIZE(msm8994_rpmpds), + .max_state = MAX_CORNER_RPMPD_STATE, +}; + /* msm8996 RPM Power domains */ DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1); DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2); @@ -302,6 +329,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, + { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc }, { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 7714487ac76b..d711e250cf2c 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -94,6 +94,15 @@ #define MSM8976_VDDMX_AO 4 #define MSM8976_VDDMX_VFL 5 +/* MSM8994 Power Domain Indexes */ +#define MSM8994_VDDCX 0 +#define MSM8994_VDDCX_AO 1 +#define MSM8994_VDDCX_VFC 2 +#define MSM8994_VDDMX 3 +#define MSM8994_VDDMX_AO 4 +#define MSM8994_VDDGFX 5 +#define MSM8994_VDDGFX_VFC 6 + /* MSM8996 Power Domain Indexes */ #define MSM8996_VDDCX 0 #define MSM8996_VDDCX_AO 1 -- cgit v1.2.3 From 94e9dd43cf327366388c8f146bccdc6322c0d999 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Thu, 21 Jan 2021 01:03:59 -0800 Subject: memory: ti-aemif: Drop child node when jumping out loop Call of_node_put() to decrement the reference count of the child node child_np when jumping out of the loop body of for_each_available_child_of_node(), which is a macro that increments and decrements the reference count of child node. If the loop is broken, the reference of the child node should be dropped manually. Fixes: 5a7c81547c1d ("memory: ti-aemif: introduce AEMIF driver") Signed-off-by: Pan Bian Link: https://lore.kernel.org/r/20210121090359.61763-1-bianpan2016@163.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/ti-aemif.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index 159a16f5e7d6..51d20c2ccb75 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -378,8 +378,10 @@ static int aemif_probe(struct platform_device *pdev) */ for_each_available_child_of_node(np, child_np) { ret = of_aemif_parse_abus_config(pdev, child_np); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata && pdata->num_abus_data > 0) { for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) { @@ -405,8 +407,10 @@ static int aemif_probe(struct platform_device *pdev) for_each_available_child_of_node(np, child_np) { ret = of_platform_populate(child_np, NULL, dev_lookup, dev); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata) { for (i = 0; i < pdata->num_sub_devices; i++) { -- cgit v1.2.3 From 975435132ecfef8de2118668c9f4f95086a0aae5 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:34 +0200 Subject: drivers: soc: atmel: add null entry at the end of at91_soc_allowed_list[] of_match_node() calls __of_match_node() which loops though the entries of matches array. It stops when condition: (matches->name[0] || matches->type[0] || matches->compatible[0]) is false. Thus, add a null entry at the end of at91_soc_allowed_list[] array. Fixes: caab13b49604 ("drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs") Cc: stable@vger.kernel.org #4.12+ Signed-off-by: Claudiu Beznea Signed-off-by: Arnd Bergmann Signed-off-by: Nicolas Ferre --- drivers/soc/atmel/soc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 728d461ad6d6..698d21f50516 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -275,7 +275,8 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = { { .compatible = "atmel,at91rm9200", }, { .compatible = "atmel,at91sam9", }, { .compatible = "atmel,sama5", }, - { .compatible = "atmel,samv7", } + { .compatible = "atmel,samv7", }, + { } }; static int __init atmel_soc_device_init(void) -- cgit v1.2.3 From 8eb2f88c6084b9dc69147abb3d24dafe36ecda8a Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:32 +0200 Subject: drivers: soc: atmel: use GENMASK Use GENMASK() to define CIDR match mask. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611318097-8970-3-git-send-email-claudiu.beznea@microchip.com --- drivers/soc/atmel/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 698d21f50516..c3f920ee5c6f 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -27,7 +27,7 @@ #define AT91_CHIPID_EXID 0x04 #define AT91_CIDR_VERSION(x) ((x) & 0x1f) #define AT91_CIDR_EXT BIT(31) -#define AT91_CIDR_MATCH_MASK 0x7fffffe0 +#define AT91_CIDR_MATCH_MASK GENMASK(30, 5) static const struct at91_soc __initconst socs[] = { #ifdef CONFIG_SOC_AT91RM9200 -- cgit v1.2.3 From 11272a373c44a5bea3a1dd051a7e84e396926c14 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:33 +0200 Subject: drivers: soc: atmel: fix "__initconst should be placed after socs[]" warning Fix checkpatch.pl warning: "__initconst should be placed after socs[]". Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611318097-8970-4-git-send-email-claudiu.beznea@microchip.com --- drivers/soc/atmel/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index c3f920ee5c6f..03f3c742716c 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -29,7 +29,7 @@ #define AT91_CIDR_EXT BIT(31) #define AT91_CIDR_MATCH_MASK GENMASK(30, 5) -static const struct at91_soc __initconst socs[] = { +static const struct at91_soc socs[] __initconst = { #ifdef CONFIG_SOC_AT91RM9200 AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), #endif -- cgit v1.2.3 From af3a10513cd628269c3207bc50b8a5886c566ec4 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:35 +0200 Subject: drivers: soc: atmel: add per soc id and version match masks SAMA7G5 has different masks for chip ID and chip version on CIDR register compared to previous AT91 SoCs. For this the commit adapts the code for SAMA7G5 addition by introducing 2 new members in struct at91_soc and fill them properly and also preparing the parsing of proper DT binding. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611318097-8970-6-git-send-email-claudiu.beznea@microchip.com --- drivers/soc/atmel/soc.c | 199 ++++++++++++++++++++++++++++++++---------------- drivers/soc/atmel/soc.h | 7 +- 2 files changed, 140 insertions(+), 66 deletions(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 03f3c742716c..f9052f45cb3e 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -25,135 +25,200 @@ #define AT91_DBGU_EXID 0x44 #define AT91_CHIPID_CIDR 0x00 #define AT91_CHIPID_EXID 0x04 -#define AT91_CIDR_VERSION(x) ((x) & 0x1f) +#define AT91_CIDR_VERSION(x, m) ((x) & (m)) +#define AT91_CIDR_VERSION_MASK GENMASK(4, 0) #define AT91_CIDR_EXT BIT(31) #define AT91_CIDR_MATCH_MASK GENMASK(30, 5) static const struct at91_soc socs[] __initconst = { #ifdef CONFIG_SOC_AT91RM9200 - AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), + AT91_SOC(AT91RM9200_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91rm9200 BGA", "at91rm9200"), #endif #ifdef CONFIG_SOC_AT91SAM9 - AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL), - AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL), - AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL), - AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL), - AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH, + AT91_SOC(AT91SAM9260_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9260", NULL), + AT91_SOC(AT91SAM9261_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9261", NULL), + AT91_SOC(AT91SAM9263_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9263", NULL), + AT91_SOC(AT91SAM9G20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9g20", NULL), + AT91_SOC(AT91SAM9RL64_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9rl64", NULL), + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9M11_EXID_MATCH, "at91sam9m11", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9M10_EXID_MATCH, "at91sam9m10", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G46_EXID_MATCH, "at91sam9g46", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G45_EXID_MATCH, "at91sam9g45", "at91sam9g45"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G15_EXID_MATCH, "at91sam9g15", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G35_EXID_MATCH, "at91sam9g35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9X35_EXID_MATCH, "at91sam9x35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G25_EXID_MATCH, "at91sam9g25", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9X25_EXID_MATCH, "at91sam9x25", "at91sam9x5"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9CN12_EXID_MATCH, "at91sam9cn12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9N12_EXID_MATCH, "at91sam9n12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9CN11_EXID_MATCH, "at91sam9cn11", "at91sam9n12"), - AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), - AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), - AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), + AT91_SOC(AT91SAM9XE128_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe128", "at91sam9xe128"), + AT91_SOC(AT91SAM9XE256_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe256", "at91sam9xe256"), + AT91_SOC(AT91SAM9XE512_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe512", "at91sam9xe512"), #endif #ifdef CONFIG_SOC_SAM9X60 - AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_EXID_MATCH, "sam9x60", "sam9x60"), + AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, + "sam9x60", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D5M_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 64MiB DDR2 SiP", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D1G_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 128MiB DDR2 SiP", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D6K_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 8MiB SDRAM SiP", "sam9x60"), #endif #ifdef CONFIG_SOC_SAMA5 - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D21CU_EXID_MATCH, "sama5d21", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D22CU_EXID_MATCH, "sama5d22", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D225C_D1M_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D225C_D1M_EXID_MATCH, "sama5d225c 16MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D23CU_EXID_MATCH, "sama5d23", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D24CX_EXID_MATCH, "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D24CU_EXID_MATCH, "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D26CU_EXID_MATCH, "sama5d26", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27CU_EXID_MATCH, "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27CN_EXID_MATCH, "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_D1G_EXID_MATCH, "sama5d27c 128MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D5M_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_D5M_EXID_MATCH, "sama5d27c 64MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_LD1G_EXID_MATCH, "sama5d27c 128MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD2G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_LD2G_EXID_MATCH, "sama5d27c 256MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28CU_EXID_MATCH, "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28CN_EXID_MATCH, "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_D1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_D1G_EXID_MATCH, "sama5d28c 128MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_LD1G_EXID_MATCH, "sama5d28c 128MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD2G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_LD2G_EXID_MATCH, "sama5d28c 256MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D31_EXID_MATCH, "sama5d31", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D33_EXID_MATCH, "sama5d33", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D34_EXID_MATCH, "sama5d34", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D35_EXID_MATCH, "sama5d35", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D36_EXID_MATCH, "sama5d36", "sama5d3"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D41_EXID_MATCH, "sama5d41", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D42_EXID_MATCH, "sama5d42", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D43_EXID_MATCH, "sama5d43", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D44_EXID_MATCH, "sama5d44", "sama5d4"), #endif #ifdef CONFIG_SOC_SAMV7 - AT91_SOC(SAME70Q21_CIDR_MATCH, SAME70Q21_EXID_MATCH, + AT91_SOC(SAME70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAME70Q21_EXID_MATCH, "same70q21", "same7"), - AT91_SOC(SAME70Q20_CIDR_MATCH, SAME70Q20_EXID_MATCH, + AT91_SOC(SAME70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAME70Q20_EXID_MATCH, "same70q20", "same7"), - AT91_SOC(SAME70Q19_CIDR_MATCH, SAME70Q19_EXID_MATCH, + AT91_SOC(SAME70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK + AT91_CIDR_VERSION_MASK, SAME70Q19_EXID_MATCH, "same70q19", "same7"), - AT91_SOC(SAMS70Q21_CIDR_MATCH, SAMS70Q21_EXID_MATCH, + AT91_SOC(SAMS70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q21_EXID_MATCH, "sams70q21", "sams7"), - AT91_SOC(SAMS70Q20_CIDR_MATCH, SAMS70Q20_EXID_MATCH, + AT91_SOC(SAMS70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q20_EXID_MATCH, "sams70q20", "sams7"), - AT91_SOC(SAMS70Q19_CIDR_MATCH, SAMS70Q19_EXID_MATCH, + AT91_SOC(SAMS70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q19_EXID_MATCH, "sams70q19", "sams7"), - AT91_SOC(SAMV71Q21_CIDR_MATCH, SAMV71Q21_EXID_MATCH, + AT91_SOC(SAMV71Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q21_EXID_MATCH, "samv71q21", "samv7"), - AT91_SOC(SAMV71Q20_CIDR_MATCH, SAMV71Q20_EXID_MATCH, + AT91_SOC(SAMV71Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q20_EXID_MATCH, "samv71q20", "samv7"), - AT91_SOC(SAMV71Q19_CIDR_MATCH, SAMV71Q19_EXID_MATCH, + AT91_SOC(SAMV71Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q19_EXID_MATCH, "samv71q19", "samv7"), - AT91_SOC(SAMV70Q20_CIDR_MATCH, SAMV70Q20_EXID_MATCH, + AT91_SOC(SAMV70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV70Q20_EXID_MATCH, "samv70q20", "samv7"), - AT91_SOC(SAMV70Q19_CIDR_MATCH, SAMV70Q19_EXID_MATCH, + AT91_SOC(SAMV70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV70Q19_EXID_MATCH, "samv70q19", "samv7"), #endif { /* sentinel */ }, @@ -191,8 +256,12 @@ static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) { struct device_node *np; void __iomem *regs; + static const struct of_device_id chipids[] = { + { .compatible = "atmel,sama5d2-chipid" }, + { }, + }; - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); + np = of_find_matching_node(NULL, chipids); if (!np) return -ENODEV; @@ -235,7 +304,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) } for (soc = socs; soc->name; soc++) { - if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) + if (soc->cidr_match != (cidr & soc->cidr_mask)) continue; if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) @@ -254,7 +323,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) soc_dev_attr->family = soc->family; soc_dev_attr->soc_id = soc->name; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", - AT91_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr, soc->version_mask)); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { kfree(soc_dev_attr->revision); @@ -266,7 +335,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) if (soc->family) pr_info("Detected SoC family: %s\n", soc->family); pr_info("Detected SoC: %s, revision %X\n", soc->name, - AT91_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr, soc->version_mask)); return soc_dev; } diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h index 5849846a69d6..02198a4de22b 100644 --- a/drivers/soc/atmel/soc.h +++ b/drivers/soc/atmel/soc.h @@ -16,14 +16,19 @@ struct at91_soc { u32 cidr_match; + u32 cidr_mask; + u32 version_mask; u32 exid_match; const char *name; const char *family; }; -#define AT91_SOC(__cidr, __exid, __name, __family) \ +#define AT91_SOC(__cidr, __cidr_mask, __version_mask, __exid, \ + __name, __family) \ { \ .cidr_match = (__cidr), \ + .cidr_mask = (__cidr_mask), \ + .version_mask = (__version_mask), \ .exid_match = (__exid), \ .name = (__name), \ .family = (__family), \ -- cgit v1.2.3 From 65d41b143329669e46f5306b867ac97b3beb38df Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:36 +0200 Subject: dt-bindings: atmel-sysreg: add "microchip, sama7g5-chipid" Add DT binding for SAMA7G5's CHIPID. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611318097-8970-7-git-send-email-claudiu.beznea@microchip.com --- Documentation/devicetree/bindings/arm/atmel-sysregs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index 62cd4e89817c..67719f15eb4c 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -1,7 +1,7 @@ Atmel system registers Chipid required properties: -- compatible: Should be "atmel,sama5d2-chipid" +- compatible: Should be "atmel,sama5d2-chipid" or "microchip,sama7g5-chipid" - reg : Should contain registers location and length PIT Timer required properties: -- cgit v1.2.3 From f12a29cb566699614266471342872193db1a1f52 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 22 Jan 2021 14:21:37 +0200 Subject: drivers: soc: atmel: add support for sama7g5 Add support for SAMA7G5 SoCs. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611318097-8970-8-git-send-email-claudiu.beznea@microchip.com --- drivers/soc/atmel/soc.c | 18 ++++++++++++++++++ drivers/soc/atmel/soc.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index f9052f45cb3e..bc8e72fd431a 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -27,8 +27,10 @@ #define AT91_CHIPID_EXID 0x04 #define AT91_CIDR_VERSION(x, m) ((x) & (m)) #define AT91_CIDR_VERSION_MASK GENMASK(4, 0) +#define AT91_CIDR_VERSION_MASK_SAMA7G5 GENMASK(3, 0) #define AT91_CIDR_EXT BIT(31) #define AT91_CIDR_MATCH_MASK GENMASK(30, 5) +#define AT91_CIDR_MASK_SAMA7G5 GENMASK(27, 5) static const struct at91_soc socs[] __initconst = { #ifdef CONFIG_SOC_AT91RM9200 @@ -220,6 +222,20 @@ static const struct at91_soc socs[] __initconst = { AT91_SOC(SAMV70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, AT91_CIDR_VERSION_MASK, SAMV70Q19_EXID_MATCH, "samv70q19", "samv7"), +#endif +#ifdef CONFIG_SOC_SAMA7 + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G51_EXID_MATCH, + "sama7g51", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G52_EXID_MATCH, + "sama7g52", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G53_EXID_MATCH, + "sama7g53", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G54_EXID_MATCH, + "sama7g54", "sama7g5"), #endif { /* sentinel */ }, }; @@ -258,6 +274,7 @@ static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) void __iomem *regs; static const struct of_device_id chipids[] = { { .compatible = "atmel,sama5d2-chipid" }, + { .compatible = "microchip,sama7g5-chipid" }, { }, }; @@ -345,6 +362,7 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = { { .compatible = "atmel,at91sam9", }, { .compatible = "atmel,sama5", }, { .compatible = "atmel,samv7", }, + { .compatible = "microchip,sama7g5", }, { } }; diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h index 02198a4de22b..93c212533ff0 100644 --- a/drivers/soc/atmel/soc.h +++ b/drivers/soc/atmel/soc.h @@ -48,6 +48,7 @@ at91_soc_init(const struct at91_soc *socs); #define AT91SAM9X5_CIDR_MATCH 0x019a05a0 #define AT91SAM9N12_CIDR_MATCH 0x019a07a0 #define SAM9X60_CIDR_MATCH 0x019b35a0 +#define SAMA7G5_CIDR_MATCH 0x00162100 #define AT91SAM9M11_EXID_MATCH 0x00000001 #define AT91SAM9M10_EXID_MATCH 0x00000002 @@ -69,6 +70,11 @@ at91_soc_init(const struct at91_soc *socs); #define SAM9X60_D1G_EXID_MATCH 0x00000010 #define SAM9X60_D6K_EXID_MATCH 0x00000011 +#define SAMA7G51_EXID_MATCH 0x3 +#define SAMA7G52_EXID_MATCH 0x2 +#define SAMA7G53_EXID_MATCH 0x1 +#define SAMA7G54_EXID_MATCH 0x0 + #define AT91SAM9XE128_CIDR_MATCH 0x329973a0 #define AT91SAM9XE256_CIDR_MATCH 0x329a93a0 #define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 -- cgit v1.2.3 From cd9168b4377932a6494d464db1ddd3f63e41fce3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 26 Jan 2021 11:29:30 +0200 Subject: drivers: soc: atmel: add spdx license identifier Add SPDX-License-Identifier. Signed-off-by: Claudiu Beznea [nicolas.ferre@microhcip.com: remove license boilerplate now it's useless] Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/1611653376-24168-2-git-send-email-claudiu.beznea@microchip.com --- drivers/soc/atmel/soc.c | 6 +----- drivers/soc/atmel/soc.h | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index bc8e72fd431a..a2967846809f 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015 Atmel * * Alexandre Belloni Date: Tue, 26 Jan 2021 14:00:55 +0800 Subject: memory: mtk-smi: Allow building as module Add support for building the SMI driver as module. Switch MTK_SMI to tristate, and add module_exit/module_license. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210126060055.11050-1-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 2 +- drivers/memory/mtk-smi.c | 9 +++++++++ include/soc/mediatek/smi.h | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 7e01b5157f40..7d9d33d8ebf6 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -173,7 +173,7 @@ config JZ4780_NEMC memory devices such as NAND and SRAM. config MTK_SMI - bool "Mediatek SoC Memory Controller driver" if COMPILE_TEST + tristate "MediaTek SoC Memory Controller driver" if COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST help This driver is for the Memory Controller module in MediaTek SoCs, diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index c07bb0b3144b..40c02d7315f6 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -597,3 +597,12 @@ static int __init mtk_smi_init(void) return platform_register_drivers(smidrivers, ARRAY_SIZE(smidrivers)); } module_init(mtk_smi_init); + +static void __exit mtk_smi_exit(void) +{ + platform_unregister_drivers(smidrivers, ARRAY_SIZE(smidrivers)); +} +module_exit(mtk_smi_exit); + +MODULE_DESCRIPTION("MediaTek SMI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h index 5a34b87d89e3..29e2fb8f33d6 100644 --- a/include/soc/mediatek/smi.h +++ b/include/soc/mediatek/smi.h @@ -9,7 +9,7 @@ #include #include -#ifdef CONFIG_MTK_SMI +#if IS_ENABLED(CONFIG_MTK_SMI) #define MTK_LARB_NR_MAX 16 -- cgit v1.2.3 From e161ce8e4cc12f2c681b13a160f709d84dee4d4f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 27 Jan 2021 18:00:50 +0530 Subject: soc: qcom: aoss: Add SM8350 compatible Add SM8350 compatible to the qcom_aoss binding and driver. Acked-by: Rob Herring Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20210127123054.263231-3-vkoul@kernel.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt | 1 + drivers/soc/qcom/qcom_aoss.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt index 953add19e937..19c059e44681 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt @@ -20,6 +20,7 @@ power-domains. "qcom,sdm845-aoss-qmp" "qcom,sm8150-aoss-qmp" "qcom,sm8250-aoss-qmp" + "qcom,sm8350-aoss-qmp" - reg: Usage: required diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index b5840d624bc6..53acb9423bd6 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -600,6 +600,7 @@ static const struct of_device_id qmp_dt_match[] = { { .compatible = "qcom,sdm845-aoss-qmp", }, { .compatible = "qcom,sm8150-aoss-qmp", }, { .compatible = "qcom,sm8250-aoss-qmp", }, + { .compatible = "qcom,sm8350-aoss-qmp", }, {} }; MODULE_DEVICE_TABLE(of, qmp_dt_match); -- cgit v1.2.3 From 8b8f095b9076ca61107c0910c9273afd1dfa1f04 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Jan 2021 11:34:07 -0800 Subject: soc: bcm: brcmstb: Remove soc_is_brcmstb() We have no in tree or out of tree users of this function, remove it and the header providing its prototype. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/common.c | 17 ----------------- include/soc/brcmstb/common.h | 12 ------------ 2 files changed, 29 deletions(-) delete mode 100644 include/soc/brcmstb/common.h diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c index d33a383701dd..e87dfc6660f3 100644 --- a/drivers/soc/bcm/brcmstb/common.c +++ b/drivers/soc/bcm/brcmstb/common.c @@ -11,8 +11,6 @@ #include #include -#include - static u32 family_id; static u32 product_id; @@ -21,21 +19,6 @@ static const struct of_device_id brcmstb_machine_match[] = { { } }; -bool soc_is_brcmstb(void) -{ - const struct of_device_id *match; - struct device_node *root; - - root = of_find_node_by_path("/"); - if (!root) - return false; - - match = of_match_node(brcmstb_machine_match, root); - of_node_put(root); - - return match != NULL; -} - u32 brcmstb_get_family_id(void) { return family_id; diff --git a/include/soc/brcmstb/common.h b/include/soc/brcmstb/common.h deleted file mode 100644 index e4fe76856de9..000000000000 --- a/include/soc/brcmstb/common.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright © 2014 NVIDIA Corporation - * Copyright © 2015 Broadcom Corporation - */ - -#ifndef __SOC_BRCMSTB_COMMON_H__ -#define __SOC_BRCMSTB_COMMON_H__ - -bool soc_is_brcmstb(void); - -#endif /* __SOC_BRCMSTB_COMMON_H__ */ -- cgit v1.2.3 From aec8535edccb943adc067d184af1a3370f5b9568 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 18 Jan 2021 18:22:36 +0300 Subject: soc: qcom: socinfo: Remove unwanted le32_to_cpu() Remove extra le32_to_cpu() conversion, data is already converted from le32 to cpu endianness. This fixes two following warnings: drivers/soc/qcom/socinfo.c:322:36: sparse: sparse: cast to restricted __le32 drivers/soc/qcom/socinfo.c:323:36: sparse: sparse: cast to restricted __le32 Signed-off-by: Dmitry Baryshkov Fixes: 734c78e7febf ("soc: qcom: socinfo: add info from PMIC models array") Link: https://lore.kernel.org/r/20210118152236.514776-1-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 5b4ad24a022b..f6cfb79338f0 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -334,8 +334,8 @@ static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) seq_printf(seq, "%s %u.%u\n", pmic_models[model], - SOCINFO_MAJOR(le32_to_cpu(die_rev)), - SOCINFO_MINOR(le32_to_cpu(die_rev))); + SOCINFO_MAJOR(die_rev), + SOCINFO_MINOR(die_rev)); else seq_printf(seq, "unknown (%d)\n", model); } -- cgit v1.2.3 From 59657d55d1a04fa5d50f96487c96c1d82f02a7f6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:47 +0000 Subject: dt-bindings: sram: sunxi-sram: Add H616 compatible string The H616 adds a second EMAC clock register. We don't know about the exact SRAM properties yet, so this gets omitted for now. Signed-off-by: Andre Przywara Acked-by: Rob Herring Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-8-andre.przywara@arm.com --- .../devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml index b66a07e21d1e..1c426c211e36 100644 --- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml +++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml @@ -49,6 +49,7 @@ properties: - items: - const: allwinner,suniv-f1c100s-system-control - const: allwinner,sun4i-a10-system-control + - const: allwinner,sun50i-h616-system-control reg: maxItems: 1 -- cgit v1.2.3 From 9117d0c975b8e1596320c9f21f8ba9b9ecc79cbd Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:48 +0000 Subject: soc: sunxi: sram: Add support for more than one EMAC clock The Allwinner H616 adds a second EMAC clock register at offset 0x34, for controlling the second EMAC in this chip. Allow to extend the regmap in this case, to cover more than the current 4 bytes exported. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-9-andre.przywara@arm.com --- drivers/soc/sunxi/sunxi_sram.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index d4c7bd59429e..42833e33a96c 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev) EXPORT_SYMBOL(sunxi_sram_release); struct sunxi_sramc_variant { - bool has_emac_clock; + int num_emac_clocks; }; static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { @@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { }; static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, }; static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, +}; + +static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { + .num_emac_clocks = 2, }; #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { - if (reg == SUNXI_SRAM_EMAC_CLOCK_REG) - return true; - return false; + const struct sunxi_sramc_variant *variant; + + variant = of_device_get_match_data(dev); + + if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) + return false; + if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return false; + + return true; } static struct regmap_config sunxi_sram_emac_clock_regmap = { @@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG, + .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (!d) return -ENOMEM; - if (variant->has_emac_clock) { + if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun50i-h5-system-control", .data = &sun50i_a64_sramc_variant, }, + { + .compatible = "allwinner,sun50i-h616-system-control", + .data = &sun50i_h616_sramc_variant, + }, { }, }; MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); -- cgit v1.2.3 From 308e78946a73e2bfe0ebd4ca9559c153c80bd45f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:54 +0000 Subject: dt-bindings: bus: rsb: Add H616 compatible string Add the obvious compatible name to the existing RSB binding, and pair it with the existing A23 fallback compatible string, as the devices are compatible. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-15-andre.przywara@arm.com --- Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml index 32d33b983d66..3d719f468a5b 100644 --- a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml +++ b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml @@ -21,7 +21,9 @@ properties: oneOf: - const: allwinner,sun8i-a23-rsb - items: - - const: allwinner,sun8i-a83t-rsb + - enum: + - allwinner,sun8i-a83t-rsb + - allwinner,sun50i-h616-rsb - const: allwinner,sun8i-a23-rsb reg: -- cgit v1.2.3 From 25d987706abce0a425332a41ec984390fd03350a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 27 Jan 2021 15:46:22 +0530 Subject: memory: tegra: Remove calls to dev_pm_opp_set_clkname() There is no point calling dev_pm_opp_set_clkname() with the "name" parameter set to NULL, this is already done by the OPP core at setup time and should work as it is. Signed-off-by: Viresh Kumar Reviewed-by: Dmitry Osipenko Tested-by: Dmitry Osipenko Link: https://lore.kernel.org/r/0f22cc1791d8b88c50a9790c2dc19455b34ec7b0.1611742564.git.viresh.kumar@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124-emc.c | 13 ++----------- drivers/memory/tegra/tegra20-emc.c | 13 ++----------- drivers/memory/tegra/tegra30-emc.c | 13 ++----------- 3 files changed, 6 insertions(+), 33 deletions(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index 9706550bdd5d..bee8d9f79b04 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1399,21 +1399,14 @@ err_msg: static int tegra_emc_opp_table_init(struct tegra_emc *emc) { u32 hw_version = BIT(tegra_sku_info.soc_speedo_id); - struct opp_table *clk_opp_table, *hw_opp_table; + struct opp_table *hw_opp_table; int err; - clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL); - err = PTR_ERR_OR_ZERO(clk_opp_table); - if (err) { - dev_err(emc->dev, "failed to set OPP clk: %d\n", err); - return err; - } - hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1); err = PTR_ERR_OR_ZERO(hw_opp_table); if (err) { dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err); - goto put_clk_table; + return err; } err = dev_pm_opp_of_add_table(emc->dev); @@ -1442,8 +1435,6 @@ remove_table: dev_pm_opp_of_remove_table(emc->dev); put_hw_table: dev_pm_opp_put_supported_hw(hw_opp_table); -put_clk_table: - dev_pm_opp_put_clkname(clk_opp_table); return err; } diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c index 686aaf477d8a..d653a6be8d7f 100644 --- a/drivers/memory/tegra/tegra20-emc.c +++ b/drivers/memory/tegra/tegra20-emc.c @@ -911,21 +911,14 @@ err_msg: static int tegra_emc_opp_table_init(struct tegra_emc *emc) { u32 hw_version = BIT(tegra_sku_info.soc_process_id); - struct opp_table *clk_opp_table, *hw_opp_table; + struct opp_table *hw_opp_table; int err; - clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL); - err = PTR_ERR_OR_ZERO(clk_opp_table); - if (err) { - dev_err(emc->dev, "failed to set OPP clk: %d\n", err); - return err; - } - hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1); err = PTR_ERR_OR_ZERO(hw_opp_table); if (err) { dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err); - goto put_clk_table; + return err; } err = dev_pm_opp_of_add_table(emc->dev); @@ -954,8 +947,6 @@ remove_table: dev_pm_opp_of_remove_table(emc->dev); put_hw_table: dev_pm_opp_put_supported_hw(hw_opp_table); -put_clk_table: - dev_pm_opp_put_clkname(clk_opp_table); return err; } diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index 44ac155936aa..6985da0ffb35 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -1483,21 +1483,14 @@ err_msg: static int tegra_emc_opp_table_init(struct tegra_emc *emc) { u32 hw_version = BIT(tegra_sku_info.soc_speedo_id); - struct opp_table *clk_opp_table, *hw_opp_table; + struct opp_table *hw_opp_table; int err; - clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL); - err = PTR_ERR_OR_ZERO(clk_opp_table); - if (err) { - dev_err(emc->dev, "failed to set OPP clk: %d\n", err); - return err; - } - hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1); err = PTR_ERR_OR_ZERO(hw_opp_table); if (err) { dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err); - goto put_clk_table; + return err; } err = dev_pm_opp_of_add_table(emc->dev); @@ -1526,8 +1519,6 @@ remove_table: dev_pm_opp_of_remove_table(emc->dev); put_hw_table: dev_pm_opp_put_supported_hw(hw_opp_table); -put_clk_table: - dev_pm_opp_put_clkname(clk_opp_table); return err; } -- cgit v1.2.3 From 2241ed9205ed91072d20ae10ad6904dc2bec5612 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 12 Nov 2020 16:21:49 +1300 Subject: bus: mvebu-mbus: make iounmap() symmetric with ioremap() make coccicheck complains: ./drivers/bus/mvebu-mbus.c:1113:2-8: ERROR: missing iounmap; ioremap on line 1106 and execution via conditional on line 1111 It took some staring but I don't think there is a problem because the file global `mbus_state` is passed mvebu_mbus_common_init() as the `mbus` parameter so `mbus_state.mbuswins_base` and `mbus->mbuswins_base` are the same thing. But this is confusing for anyone reading the code and one less complaint from coccicheck would be nice so lets fix it. Signed-off-by: Chris Packham Acked-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- drivers/bus/mvebu-mbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 2519ceede64b..dd9e7343a5e3 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -1111,7 +1111,7 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size); if (!mbus->sdramwins_base) { - iounmap(mbus_state.mbuswins_base); + iounmap(mbus->mbuswins_base); return -ENOMEM; } -- cgit v1.2.3 From c70d0f16f38c3c25830db2854203444b566d30a9 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 9 Dec 2020 14:32:36 +0100 Subject: dt-bindings: power: Add MT8167 power domains Add power domains dt-bindings for MT8167. Signed-off-by: Fabien Parent Acked-by: Rob Herring Link: https://lore.kernel.org/r/20201209133238.384030-1-fparent@baylibre.com Signed-off-by: Matthias Brugger --- .../bindings/power/mediatek,power-controller.yaml | 2 ++ include/dt-bindings/power/mt8167-power.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 include/dt-bindings/power/mt8167-power.h diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml index d14cb9bac849..52e77315c163 100644 --- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml +++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml @@ -23,6 +23,7 @@ properties: compatible: enum: + - mediatek,mt8167-power-controller - mediatek,mt8173-power-controller - mediatek,mt8183-power-controller - mediatek,mt8192-power-controller @@ -59,6 +60,7 @@ patternProperties: reg: description: | Power domain index. Valid values are defined in: + "include/dt-bindings/power/mt8167-power.h" - for MT8167 type power domain. "include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain. "include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain. "include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain. diff --git a/include/dt-bindings/power/mt8167-power.h b/include/dt-bindings/power/mt8167-power.h new file mode 100644 index 000000000000..c8ec9983a4bc --- /dev/null +++ b/include/dt-bindings/power/mt8167-power.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _DT_BINDINGS_POWER_MT8167_POWER_H +#define _DT_BINDINGS_POWER_MT8167_POWER_H + +#define MT8167_POWER_DOMAIN_MM 0 +#define MT8167_POWER_DOMAIN_VDEC 1 +#define MT8167_POWER_DOMAIN_ISP 2 +#define MT8167_POWER_DOMAIN_CONN 3 +#define MT8167_POWER_DOMAIN_MFG_ASYNC 4 +#define MT8167_POWER_DOMAIN_MFG_2D 5 +#define MT8167_POWER_DOMAIN_MFG 6 + +#endif /* _DT_BINDINGS_POWER_MT8167_POWER_H */ -- cgit v1.2.3 From 207f13b419a60c56fb75baeb3d668de080514354 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 9 Dec 2020 14:32:37 +0100 Subject: soc: mediatek: pm-domains: Add support for mt8167 Add the needed board data to support mt8167 SoC. Signed-off-by: Fabien Parent Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20201209133238.384030-2-fparent@baylibre.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mt8167-pm-domains.h | 86 ++++++++++++++++++++++++++++++++ drivers/soc/mediatek/mtk-pm-domains.c | 5 ++ drivers/soc/mediatek/mtk-pm-domains.h | 1 + include/linux/soc/mediatek/infracfg.h | 8 +++ 4 files changed, 100 insertions(+) create mode 100644 drivers/soc/mediatek/mt8167-pm-domains.h diff --git a/drivers/soc/mediatek/mt8167-pm-domains.h b/drivers/soc/mediatek/mt8167-pm-domains.h new file mode 100644 index 000000000000..ad0b8dfa0527 --- /dev/null +++ b/drivers/soc/mediatek/mt8167-pm-domains.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H +#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H + +#include "mtk-pm-domains.h" +#include + +#define MT8167_PWR_STATUS_MFG_2D BIT(24) +#define MT8167_PWR_STATUS_MFG_ASYNC BIT(25) + +/* + * MT8167 power domain support + */ + +static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { + [MT8167_POWER_DOMAIN_MM] = { + .sta_mask = PWR_STATUS_DISP, + .ctl_offs = SPM_DIS_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI | + MT8167_TOP_AXI_PROT_EN_MCU_MM), + }, + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_VDEC] = { + .sta_mask = PWR_STATUS_VDEC, + .ctl_offs = SPM_VDE_PWR_CON, + .sram_pdn_bits = GENMASK(8, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_ISP] = { + .sta_mask = PWR_STATUS_ISP, + .ctl_offs = SPM_ISP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(13, 12), + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_MFG_ASYNC] = { + .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC, + .ctl_offs = SPM_MFG_ASYNC_PWR_CON, + .sram_pdn_bits = 0, + .sram_pdn_ack_bits = 0, + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG | + MT8167_TOP_AXI_PROT_EN_MFG_EMI), + }, + }, + [MT8167_POWER_DOMAIN_MFG_2D] = { + .sta_mask = MT8167_PWR_STATUS_MFG_2D, + .ctl_offs = SPM_MFG_2D_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + }, + [MT8167_POWER_DOMAIN_MFG] = { + .sta_mask = PWR_STATUS_MFG, + .ctl_offs = SPM_MFG_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + }, + [MT8167_POWER_DOMAIN_CONN] = { + .sta_mask = PWR_STATUS_CONN, + .ctl_offs = SPM_CONN_PWR_CON, + .sram_pdn_bits = GENMASK(8, 8), + .sram_pdn_ack_bits = 0, + .caps = MTK_SCPD_ACTIVE_WAKEUP, + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI | + MT8167_TOP_AXI_PROT_EN_CONN_MCU | + MT8167_TOP_AXI_PROT_EN_MCU_CONN), + }, + }, +}; + +static const struct scpsys_soc_data mt8167_scpsys_data = { + .domains_data = scpsys_domain_data_mt8167, + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167), + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, +}; + +#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */ + diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index fb70cb3b07b3..2d0d50ff35f0 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -15,6 +15,7 @@ #include #include +#include "mt8167-pm-domains.h" #include "mt8173-pm-domains.h" #include "mt8183-pm-domains.h" #include "mt8192-pm-domains.h" @@ -514,6 +515,10 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys) } static const struct of_device_id scpsys_of_match[] = { + { + .compatible = "mediatek,mt8167-power-controller", + .data = &mt8167_scpsys_data, + }, { .compatible = "mediatek,mt8173-power-controller", .data = &mt8173_scpsys_data, diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h index a2f4d8f97e05..88f5835e1648 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -14,6 +14,7 @@ #define SPM_VEN_PWR_CON 0x0230 #define SPM_ISP_PWR_CON 0x0238 #define SPM_DIS_PWR_CON 0x023c +#define SPM_CONN_PWR_CON 0x0280 #define SPM_VEN2_PWR_CON 0x0298 #define SPM_AUDIO_PWR_CON 0x029c #define SPM_MFG_2D_PWR_CON 0x02c0 diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h index e7842debc05d..4615a228da51 100644 --- a/include/linux/soc/mediatek/infracfg.h +++ b/include/linux/soc/mediatek/infracfg.h @@ -123,6 +123,14 @@ #define MT8173_TOP_AXI_PROT_EN_MFG_M1 BIT(22) #define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT BIT(23) +#define MT8167_TOP_AXI_PROT_EN_MM_EMI BIT(1) +#define MT8167_TOP_AXI_PROT_EN_MCU_MFG BIT(2) +#define MT8167_TOP_AXI_PROT_EN_CONN_EMI BIT(4) +#define MT8167_TOP_AXI_PROT_EN_MFG_EMI BIT(5) +#define MT8167_TOP_AXI_PROT_EN_CONN_MCU BIT(8) +#define MT8167_TOP_AXI_PROT_EN_MCU_CONN BIT(9) +#define MT8167_TOP_AXI_PROT_EN_MCU_MM BIT(11) + #define MT2701_TOP_AXI_PROT_EN_MM_M0 BIT(1) #define MT2701_TOP_AXI_PROT_EN_CONN_M BIT(2) #define MT2701_TOP_AXI_PROT_EN_CONN_S BIT(8) -- cgit v1.2.3 From 1570db1da9f57dfbe5dfa3010233c98947497466 Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Thu, 3 Dec 2020 07:58:55 +0800 Subject: soc: mediatek: cmdq: Remove cmdq_pkt_flush() rx_callback is a standard mailbox callback mechanism and could cover the function of proprietary cmdq_task_cb, so it is better to use the standard one instead of the proprietary one. But register rx_callback should before mbox_request_channel(), so remove cmdq_pkt_flush() and let client driver implement its own synchronous flush. Signed-off-by: Chun-Kuang Hu Link: https://lore.kernel.org/r/20201202235856.7652-1-chunkuang.hu@kernel.org Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 32 -------------------------------- include/linux/soc/mediatek/mtk-cmdq.h | 12 ------------ 2 files changed, 44 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 280d3bd9f675..3c8e4212d941 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -463,36 +463,4 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, } EXPORT_SYMBOL(cmdq_pkt_flush_async); -struct cmdq_flush_completion { - struct completion cmplt; - bool err; -}; - -static void cmdq_pkt_flush_cb(struct cmdq_cb_data data) -{ - struct cmdq_flush_completion *cmplt; - - cmplt = (struct cmdq_flush_completion *)data.data; - if (data.sta != CMDQ_CB_NORMAL) - cmplt->err = true; - else - cmplt->err = false; - complete(&cmplt->cmplt); -} - -int cmdq_pkt_flush(struct cmdq_pkt *pkt) -{ - struct cmdq_flush_completion cmplt; - int err; - - init_completion(&cmplt.cmplt); - err = cmdq_pkt_flush_async(pkt, cmdq_pkt_flush_cb, &cmplt); - if (err < 0) - return err; - wait_for_completion(&cmplt.cmplt); - - return cmplt.err ? -EFAULT : 0; -} -EXPORT_SYMBOL(cmdq_pkt_flush); - MODULE_LICENSE("GPL v2"); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 8e9996610978..ac6b5f3cba95 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -280,16 +280,4 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt); int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, void *data); -/** - * cmdq_pkt_flush() - trigger CMDQ to execute the CMDQ packet - * @pkt: the CMDQ packet - * - * Return: 0 for success; else the error code is returned - * - * Trigger CMDQ to execute the CMDQ packet. Note that this is a - * synchronous flush function. When the function returned, the recorded - * commands have been done. - */ -int cmdq_pkt_flush(struct cmdq_pkt *pkt); - #endif /* __MTK_CMDQ_H__ */ -- cgit v1.2.3 From ebfe73f7079a9ef5e6487ae8dfe48c43787118e8 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Fri, 29 Jan 2021 18:12:06 +0800 Subject: dt-bindings: power: Add domain regulator supply Some power domains (eg. mfg) needs to turn on power supply before power on. Signed-off-by: Hsin-Yi Wang Reviewed-by: Rob Herring Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20210129101208.2625249-2-hsinyi@chromium.org Signed-off-by: Matthias Brugger --- .../devicetree/bindings/power/mediatek,power-controller.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml index 52e77315c163..f234a756c193 100644 --- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml +++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml @@ -84,6 +84,9 @@ patternProperties: be specified by order, adding first the BASIC clocks followed by the SUSBSYS clocks. + domain-supply: + description: domain regulator supply. + mediatek,infracfg: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to the device containing the INFRACFG register range. @@ -132,6 +135,9 @@ patternProperties: be specified by order, adding first the BASIC clocks followed by the SUSBSYS clocks. + domain-supply: + description: domain regulator supply. + mediatek,infracfg: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to the device containing the INFRACFG register range. @@ -180,6 +186,9 @@ patternProperties: be specified by order, adding first the BASIC clocks followed by the SUSBSYS clocks. + domain-supply: + description: domain regulator supply. + mediatek,infracfg: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to the device containing the INFRACFG register range. -- cgit v1.2.3 From 1b18c0558d092b29b0d9ccdf14a6915156e6cf32 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Fri, 29 Jan 2021 18:12:07 +0800 Subject: soc: mediatek: pm-domains: Add domain regulator supply Some power domains (eg. mfg) needs to turn on power supply before power on. Signed-off-by: Hsin-Yi Wang Reviewed-by: Nicolas Boichat Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20210129101208.2625249-3-hsinyi@chromium.org Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mt8183-pm-domains.h | 1 + drivers/soc/mediatek/mtk-pm-domains.c | 42 +++++++++++++++++++++++++++++++- drivers/soc/mediatek/mtk-pm-domains.h | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/soc/mediatek/mt8183-pm-domains.h b/drivers/soc/mediatek/mt8183-pm-domains.h index 8d996c5d2682..aa5230e6c12f 100644 --- a/drivers/soc/mediatek/mt8183-pm-domains.h +++ b/drivers/soc/mediatek/mt8183-pm-domains.h @@ -38,6 +38,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), + .caps = MTK_SCPD_DOMAIN_SUPPLY, }, [MT8183_POWER_DOMAIN_MFG_CORE0] = { .sta_mask = BIT(7), diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index 2d0d50ff35f0..905ac8a0341a 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "mt8167-pm-domains.h" @@ -41,6 +42,7 @@ struct scpsys_domain { struct clk_bulk_data *subsys_clks; struct regmap *infracfg; struct regmap *smi; + struct regulator *supply; }; struct scpsys { @@ -188,6 +190,16 @@ static int scpsys_bus_protect_disable(struct scpsys_domain *pd) return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg); } +static int scpsys_regulator_enable(struct regulator *supply) +{ + return supply ? regulator_enable(supply) : 0; +} + +static int scpsys_regulator_disable(struct regulator *supply) +{ + return supply ? regulator_disable(supply) : 0; +} + static int scpsys_power_on(struct generic_pm_domain *genpd) { struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); @@ -195,10 +207,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) bool tmp; int ret; - ret = clk_bulk_enable(pd->num_clks, pd->clks); + ret = scpsys_regulator_enable(pd->supply); if (ret) return ret; + ret = clk_bulk_enable(pd->num_clks, pd->clks); + if (ret) + goto err_reg; + /* subsys power on */ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); @@ -233,6 +249,8 @@ err_disable_subsys_clks: clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks); err_pwr_ack: clk_bulk_disable(pd->num_clks, pd->clks); +err_reg: + scpsys_regulator_disable(pd->supply); return ret; } @@ -268,6 +286,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) clk_bulk_disable(pd->num_clks, pd->clks); + scpsys_regulator_disable(pd->supply); + return 0; } @@ -276,6 +296,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no { const struct scpsys_domain_data *domain_data; struct scpsys_domain *pd; + struct device_node *root_node = scpsys->dev->of_node; struct property *prop; const char *clk_name; int i, ret, num_clks; @@ -308,6 +329,25 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no pd->data = domain_data; pd->scpsys = scpsys; + if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) { + /* + * Find regulator in current power domain node. + * devm_regulator_get() finds regulator in a node and its child + * node, so set of_node to current power domain node then change + * back to original node after regulator is found for current + * power domain node. + */ + scpsys->dev->of_node = node; + pd->supply = devm_regulator_get(scpsys->dev, "domain"); + scpsys->dev->of_node = root_node; + if (IS_ERR(pd->supply)) { + dev_err_probe(scpsys->dev, PTR_ERR(pd->supply), + "%pOF: failed to get power supply.\n", + node); + return ERR_CAST(pd->supply); + } + } + pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); if (IS_ERR(pd->infracfg)) return ERR_CAST(pd->infracfg); diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h index 88f5835e1648..141dc76054e6 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -7,6 +7,7 @@ #define MTK_SCPD_FWAIT_SRAM BIT(1) #define MTK_SCPD_SRAM_ISO BIT(2) #define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3) +#define MTK_SCPD_DOMAIN_SUPPLY BIT(4) #define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) #define SPM_VDE_PWR_CON 0x0210 -- cgit v1.2.3 From dd65030295e20338bbb8238454c2e9546b6e5e17 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 13 Jan 2021 22:30:12 +0100 Subject: soc: mediatek: pm-domains: Don't print an error if child domain is deferred Child domains can be deferred by the core because one of its resources is not available yet, in such case, it will print an error, but later it will succeed to probe. Fix that using the dev_err_probe() function so it only prints an error on a real error. Signed-off-by: Enric Balletbo i Serra Reviewed-by: Hsin-Yi Wang Link: https://lore.kernel.org/r/20210113213012.67643-1-enric.balletbo@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pm-domains.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index 905ac8a0341a..b7f697666bdd 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -487,8 +487,8 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren child_pd = scpsys_add_one_domain(scpsys, child); if (IS_ERR(child_pd)) { - ret = PTR_ERR(child_pd); - dev_err(scpsys->dev, "%pOF: failed to get child domain id\n", child); + dev_err_probe(scpsys->dev, PTR_ERR(child_pd), + "%pOF: failed to get child domain id\n", child); goto err_put_node; } -- cgit v1.2.3 From ea797f699440d85489dc839b28845434e350c917 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 31 Jan 2021 20:53:43 -0800 Subject: soc: ti: pruss: Refactor the CFG sub-module init The CFG sub-module is not present on some earlier SoCs like the DA850/OMAPL-138 in the TI Davinci family. Refactor out the CFG sub-module parse and initialization logic into a separate function to make it easier to add logic for the PRUSS IP on the above legacy SoC families. Signed-off-by: Suman Anna Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 91 +++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 1d6890134312..f22ac1edbdd0 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -161,6 +161,53 @@ static struct regmap_config regmap_conf = { .reg_stride = 4, }; +static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss) +{ + struct device_node *np = dev_of_node(dev); + struct device_node *child; + struct resource res; + int ret; + + child = of_get_child_by_name(np, "cfg"); + if (!child) { + dev_err(dev, "%pOF is missing its 'cfg' node\n", child); + return -ENODEV; + } + + if (of_address_to_resource(child, 0, &res)) { + ret = -ENOMEM; + goto node_put; + } + + pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (!pruss->cfg_base) { + ret = -ENOMEM; + goto node_put; + } + + regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child, + (u64)res.start); + regmap_conf.max_register = resource_size(&res) - 4; + + pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base, + ®map_conf); + kfree(regmap_conf.name); + if (IS_ERR(pruss->cfg_regmap)) { + dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n", + PTR_ERR(pruss->cfg_regmap)); + ret = PTR_ERR(pruss->cfg_regmap); + goto node_put; + } + + ret = pruss_clk_init(pruss, child); + if (ret) + dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret); + +node_put: + of_node_put(child); + return ret; +} + static int pruss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -239,56 +286,18 @@ static int pruss_probe(struct platform_device *pdev) goto rpm_disable; } - child = of_get_child_by_name(np, "cfg"); - if (!child) { - dev_err(dev, "%pOF is missing its 'cfg' node\n", child); - ret = -ENODEV; + ret = pruss_cfg_of_init(dev, pruss); + if (ret < 0) goto rpm_put; - } - - if (of_address_to_resource(child, 0, &res)) { - ret = -ENOMEM; - goto node_put; - } - - pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res)); - if (!pruss->cfg_base) { - ret = -ENOMEM; - goto node_put; - } - - regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child, - (u64)res.start); - regmap_conf.max_register = resource_size(&res) - 4; - - pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base, - ®map_conf); - kfree(regmap_conf.name); - if (IS_ERR(pruss->cfg_regmap)) { - dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n", - PTR_ERR(pruss->cfg_regmap)); - ret = PTR_ERR(pruss->cfg_regmap); - goto node_put; - } - - ret = pruss_clk_init(pruss, child); - if (ret) { - dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret); - goto node_put; - } ret = devm_of_platform_populate(dev); if (ret) { dev_err(dev, "failed to register child devices\n"); - goto node_put; + goto rpm_put; } - of_node_put(child); - return 0; -node_put: - of_node_put(child); rpm_put: pm_runtime_put_sync(dev); rpm_disable: -- cgit v1.2.3 From a8fc8e5b8e42c4401d009143a5fd822ef3d0c9df Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 31 Jan 2021 20:58:49 -0800 Subject: soc: ti: k3-ringacc: Use of_device_get_match_data() Simplify the retrieval of getting the match data in the probe function by directly using of_device_get_match_data() instead of using of_match_node() and getting data. Signed-off-by: Suman Anna Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/k3-ringacc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index b495b0d5d0fa..312ba0f98ad7 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1517,15 +1518,13 @@ EXPORT_SYMBOL_GPL(k3_ringacc_dmarings_init); static int k3_ringacc_probe(struct platform_device *pdev) { const struct ringacc_match_data *match_data; - const struct of_device_id *match; struct device *dev = &pdev->dev; struct k3_ringacc *ringacc; int ret; - match = of_match_node(k3_ringacc_of_match, dev->of_node); - if (!match) + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) return -ENODEV; - match_data = match->data; ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL); if (!ringacc) -- cgit v1.2.3 From c7020068bf2397b60bb62a1f71ca0fe626c1f7e7 Mon Sep 17 00:00:00 2001 From: Elvira Khabirova Date: Sun, 20 Sep 2020 04:58:57 +0300 Subject: tee: fix some comment typos in header files struct tee_param: revc -> recv. TEE_IOC_SUPPL_SEND: typo introduced by copy-pasting, replace invalid description with description from the according argument struct. Signed-off-by: Elvira Khabirova Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 2 +- include/uapi/linux/tee.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index cdd049a724b1..54269e47ac9a 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -88,7 +88,7 @@ struct tee_param { * @close_session: close a session * @invoke_func: invoke a trusted function * @cancel_req: request cancel of an ongoing invoke or open - * @supp_revc: called for supplicant to get a command + * @supp_recv: called for supplicant to get a command * @supp_send: called for supplicant to send a response * @shm_register: register shared memory buffer in TEE * @shm_unregister: unregister shared memory buffer in TEE diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index d67cadf221fc..25a6c534beb1 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -355,7 +355,7 @@ struct tee_iocl_supp_send_arg { }; /** - * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function + * TEE_IOC_SUPPL_SEND - Send a response to a received request * * Takes a struct tee_ioctl_buf_data which contains a struct * tee_iocl_supp_send_arg followed by any array of struct tee_param -- cgit v1.2.3 From fda90b29e27156db1923ac1f120935991f792560 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 31 Dec 2020 19:58:26 +0800 Subject: drivers: optee: use flexible-array member instead of zero-length array Use flexible-array member introduced in C99 instead of zero-length array. Most of zero-length array was already taken care in previous patch [1]. Now modified few more cases which were not handled earlier. [1]. https://patchwork.kernel.org/patch/11394197/ Signed-off-by: Tian Tao Signed-off-by: Jens Wiklander --- drivers/tee/optee/optee_msg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 7b2d919da2ac..b1f1e902b19b 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -199,7 +199,7 @@ struct optee_msg_arg { u32 num_params; /* num_params tells the actual number of element in params */ - struct optee_msg_param params[0]; + struct optee_msg_param params[]; }; /** -- cgit v1.2.3 From bed13b5fc4f3012bdb1d7585b6eae3858321c6e7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 26 Jan 2021 15:15:07 -0600 Subject: tee: optee: fix 'physical' typos Fix misspellings of "physical". Signed-off-by: Bjorn Helgaas Signed-off-by: Jens Wiklander --- drivers/tee/optee/optee_smc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index 777ad54d4c2c..b52eb34b4237 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -139,7 +139,7 @@ struct optee_smc_call_get_os_revision_result { * optee_msg_arg. * OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, * try again later. - * OPTEE_SMC_RETURN_EBADADDR Bad physcial pointer to struct + * OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct * optee_msg_arg. * OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg * OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal -- cgit v1.2.3 From 617d8e8b347edcee6da38df0aeb671fc9c9ba19c Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Wed, 20 Jan 2021 11:14:12 +0100 Subject: optee: sync OP-TEE headers Pulls in updates in the internal headers from OP-TEE OS [1]. A few defines has been shortened, hence the changes in rpc.c. Defines not used by the driver in tee_rpc_cmd.h has been filtered out. Note that this does not change the ABI. Link: [1] https://github.com/OP-TEE/optee_os Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- drivers/tee/optee/optee_msg.h | 156 ++------------------------------------ drivers/tee/optee/optee_rpc_cmd.h | 103 +++++++++++++++++++++++++ drivers/tee/optee/optee_smc.h | 70 +++++++++++------ drivers/tee/optee/rpc.c | 39 +++++----- 4 files changed, 179 insertions(+), 189 deletions(-) create mode 100644 drivers/tee/optee/optee_rpc_cmd.h diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index b1f1e902b19b..81ff593ac4ec 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* - * Copyright (c) 2015-2019, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #ifndef _OPTEE_MSG_H #define _OPTEE_MSG_H @@ -12,11 +12,9 @@ * This file defines the OP-TEE message protocol used to communicate * with an instance of OP-TEE running in secure world. * - * This file is divided into three sections. + * This file is divided into two sections. * 1. Formatting of messages. * 2. Requests from normal world - * 3. Requests from secure world, Remote Procedure Call (RPC), handled by - * tee-supplicant. */ /***************************************************************************** @@ -54,8 +52,8 @@ * Every entry in buffer should point to a 4k page beginning (12 least * significant bits must be equal to zero). * - * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page - * offset of the user buffer. + * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold + * page offset of user buffer. * * So, entries should be placed like members of this structure: * @@ -176,17 +174,9 @@ struct optee_msg_param { * @params: the parameters supplied to the OS Command * * All normal calls to Trusted OS uses this struct. If cmd requires further - * information than what these field holds it can be passed as a parameter + * information than what these fields hold it can be passed as a parameter * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding - * attrs field). All parameters tagged as meta has to come first. - * - * Temp memref parameters can be fragmented if supported by the Trusted OS - * (when optee_smc.h is bearer of this protocol this is indicated with - * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is - * fragmented then has all but the last fragment the - * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented - * it will still be presented as a single logical memref to the Trusted - * Application. + * attrs field). All parameters tagged as meta have to come first. */ struct optee_msg_arg { u32 cmd; @@ -290,15 +280,12 @@ struct optee_msg_arg { * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The * information is passed as: * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT - * [| OPTEE_MSG_ATTR_FRAGMENT] + * [| OPTEE_MSG_ATTR_NONCONTIG] * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) * [in] param[0].u.tmem.size size (of first fragment) * [in] param[0].u.tmem.shm_ref holds shared memory reference - * ... - * The shared memory can optionally be fragmented, temp memrefs can follow - * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set. * - * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared + * OPTEE_MSG_CMD_UNREGISTER_SHM unregisters a previously registered shared * memory reference. The information is passed as: * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT * [in] param[0].u.rmem.shm_ref holds shared memory reference @@ -313,131 +300,4 @@ struct optee_msg_arg { #define OPTEE_MSG_CMD_UNREGISTER_SHM 5 #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 -/***************************************************************************** - * Part 3 - Requests from secure world, RPC - *****************************************************************************/ - -/* - * All RPC is done with a struct optee_msg_arg as bearer of information, - * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below - * - * RPC communication with tee-supplicant is reversed compared to normal - * client communication desribed above. The supplicant receives requests - * and sends responses. - */ - -/* - * Load a TA into memory, defined in tee-supplicant - */ -#define OPTEE_MSG_RPC_CMD_LOAD_TA 0 - -/* - * Reserved - */ -#define OPTEE_MSG_RPC_CMD_RPMB 1 - -/* - * File system access, defined in tee-supplicant - */ -#define OPTEE_MSG_RPC_CMD_FS 2 - -/* - * Get time - * - * Returns number of seconds and nano seconds since the Epoch, - * 1970-01-01 00:00:00 +0000 (UTC). - * - * [out] param[0].u.value.a Number of seconds - * [out] param[0].u.value.b Number of nano seconds. - */ -#define OPTEE_MSG_RPC_CMD_GET_TIME 3 - -/* - * Wait queue primitive, helper for secure world to implement a wait queue. - * - * If secure world need to wait for a secure world mutex it issues a sleep - * request instead of spinning in secure world. Conversely is a wakeup - * request issued when a secure world mutex with a thread waiting thread is - * unlocked. - * - * Waiting on a key - * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP - * [in] param[0].u.value.b wait key - * - * Waking up a key - * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP - * [in] param[0].u.value.b wakeup key - */ -#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4 -#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0 -#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1 - -/* - * Suspend execution - * - * [in] param[0].value .a number of milliseconds to suspend - */ -#define OPTEE_MSG_RPC_CMD_SUSPEND 5 - -/* - * Allocate a piece of shared memory - * - * Shared memory can optionally be fragmented, to support that additional - * spare param entries are allocated to make room for eventual fragments. - * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when - * unused. All returned temp memrefs except the last should have the - * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field. - * - * [in] param[0].u.value.a type of memory one of - * OPTEE_MSG_RPC_SHM_TYPE_* below - * [in] param[0].u.value.b requested size - * [in] param[0].u.value.c required alignment - * - * [out] param[0].u.tmem.buf_ptr physical address (of first fragment) - * [out] param[0].u.tmem.size size (of first fragment) - * [out] param[0].u.tmem.shm_ref shared memory reference - * ... - * [out] param[n].u.tmem.buf_ptr physical address - * [out] param[n].u.tmem.size size - * [out] param[n].u.tmem.shm_ref shared memory reference (same value - * as in param[n-1].u.tmem.shm_ref) - */ -#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 -/* Memory that can be shared with a non-secure user space application */ -#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0 -/* Memory only shared with non-secure kernel */ -#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1 - -/* - * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC - * - * [in] param[0].u.value.a type of memory one of - * OPTEE_MSG_RPC_SHM_TYPE_* above - * [in] param[0].u.value.b value of shared memory reference - * returned in param[0].u.tmem.shm_ref - * above - */ -#define OPTEE_MSG_RPC_CMD_SHM_FREE 7 - -/* - * Access a device on an i2c bus - * - * [in] param[0].u.value.a mode: RD(0), WR(1) - * [in] param[0].u.value.b i2c adapter - * [in] param[0].u.value.c i2c chip - * - * [in] param[1].u.value.a i2c control flags - * - * [in/out] memref[2] buffer to exchange the transfer data - * with the secure world - * - * [out] param[3].u.value.a bytes transferred by the driver - */ -#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21 -/* I2C master transfer modes */ -#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0 -#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1 -/* I2C master control flags */ -#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0) - #endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h new file mode 100644 index 000000000000..b8275140cef8 --- /dev/null +++ b/drivers/tee/optee/optee_rpc_cmd.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2021, Linaro Limited + */ + +#ifndef __OPTEE_RPC_CMD_H +#define __OPTEE_RPC_CMD_H + +/* + * All RPC is done with a struct optee_msg_arg as bearer of information, + * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below. + * Only the commands handled by the kernel driver are defined here. + * + * RPC communication with tee-supplicant is reversed compared to normal + * client communication described above. The supplicant receives requests + * and sends responses. + */ + +/* + * Get time + * + * Returns number of seconds and nano seconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + * + * [out] value[0].a Number of seconds + * [out] value[0].b Number of nano seconds. + */ +#define OPTEE_RPC_CMD_GET_TIME 3 + +/* + * Wait queue primitive, helper for secure world to implement a wait queue. + * + * If secure world needs to wait for a secure world mutex it issues a sleep + * request instead of spinning in secure world. Conversely is a wakeup + * request issued when a secure world mutex with a thread waiting thread is + * unlocked. + * + * Waiting on a key + * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP + * [in] value[0].b Wait key + * + * Waking up a key + * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP + * [in] value[0].b Wakeup key + */ +#define OPTEE_RPC_CMD_WAIT_QUEUE 4 +#define OPTEE_RPC_WAIT_QUEUE_SLEEP 0 +#define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1 + +/* + * Suspend execution + * + * [in] value[0].a Number of milliseconds to suspend + */ +#define OPTEE_RPC_CMD_SUSPEND 5 + +/* + * Allocate a piece of shared memory + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* below + * [in] value[0].b Requested size + * [in] value[0].c Required alignment + * [out] memref[0] Buffer + */ +#define OPTEE_RPC_CMD_SHM_ALLOC 6 +/* Memory that can be shared with a non-secure user space application */ +#define OPTEE_RPC_SHM_TYPE_APPL 0 +/* Memory only shared with non-secure kernel */ +#define OPTEE_RPC_SHM_TYPE_KERNEL 1 + +/* + * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* above + * [in] value[0].b Value of shared memory reference or cookie + */ +#define OPTEE_RPC_CMD_SHM_FREE 7 + +/* + * Issue master requests (read and write operations) to an I2C chip. + * + * [in] value[0].a Transfer mode (OPTEE_RPC_I2C_TRANSFER_*) + * [in] value[0].b The I2C bus (a.k.a adapter). + * 16 bit field. + * [in] value[0].c The I2C chip (a.k.a address). + * 16 bit field (either 7 or 10 bit effective). + * [in] value[1].a The I2C master control flags (ie, 10 bit address). + * 16 bit field. + * [in/out] memref[2] Buffer used for data transfers. + * [out] value[3].a Number of bytes transferred by the REE. + */ +#define OPTEE_RPC_CMD_I2C_TRANSFER 21 + +/* I2C master transfer modes */ +#define OPTEE_RPC_I2C_TRANSFER_RD 0 +#define OPTEE_RPC_I2C_TRANSFER_WR 1 + +/* I2C master control flags */ +#define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0) + +#endif /*__OPTEE_RPC_CMD_H*/ diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index b52eb34b4237..80eb763a8a80 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* - * Copyright (c) 2015-2019, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #ifndef OPTEE_SMC_H #define OPTEE_SMC_H @@ -39,10 +39,10 @@ /* * Function specified by SMC Calling convention * - * Return one of the following UIDs if using API specified in this file - * without further extentions: - * 65cb6b93-af0c-4617-8ed6-644a8d1140f8 - * see also OPTEE_SMC_UID_* in optee_msg.h + * Return the following UID if using API specified in this file + * without further extensions: + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. + * see also OPTEE_MSG_UID_* in optee_msg.h */ #define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID #define OPTEE_SMC_CALLS_UID \ @@ -53,7 +53,7 @@ /* * Function specified by SMC Calling convention * - * Returns 2.0 if using API specified in this file without further extentions. + * Returns 2.0 if using API specified in this file without further extensions. * see also OPTEE_MSG_REVISION_* in optee_msg.h */ #define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION @@ -109,8 +109,8 @@ struct optee_smc_call_get_os_revision_result { * * Call register usage: * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG - * a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg - * a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg + * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg + * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a3 Cache settings, not used if physical pointer is in a predefined shared * memory area else per OPTEE_SMC_SHM_* * a4-6 Not used @@ -214,8 +214,9 @@ struct optee_smc_get_shm_config_result { * secure world accepts command buffers located in any parts of non-secure RAM */ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) - -/* Secure world supports Shared Memory with a NULL buffer reference */ +/* Secure world is built with virtualization support */ +#define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3) +/* Secure world supports Shared Memory with a NULL reference */ #define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 @@ -245,8 +246,8 @@ struct optee_smc_exchange_capabilities_result { * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK - * a1 Upper 32bit of a 64bit Shared memory cookie - * a2 Lower 32bit of a 64bit Shared memory cookie + * a1 Upper 32 bits of a 64-bit Shared memory cookie + * a2 Lower 32 bits of a 64-bit Shared memory cookie * a3-7 Preserved * * Cache empty return register usage: @@ -293,6 +294,31 @@ struct optee_smc_disable_shm_cache_result { #define OPTEE_SMC_ENABLE_SHM_CACHE \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE) +/* + * Query OP-TEE about number of supported threads + * + * Normal World OS or Hypervisor issues this call to find out how many + * threads OP-TEE supports. That is how many standard calls can be issued + * in parallel before OP-TEE will return OPTEE_SMC_RETURN_ETHREAD_LIMIT. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_GET_THREAD_COUNT + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Number of threads + * a2-7 Preserved + * + * Error return: + * a0 OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Requested call is not implemented + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_GET_THREAD_COUNT 15 +#define OPTEE_SMC_GET_THREAD_COUNT \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT) + /* * Resume from RPC (for example after processing a foreign interrupt) * @@ -341,16 +367,16 @@ struct optee_smc_disable_shm_cache_result { * * "Return" register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. - * a1 Upper 32bits of 64bit physical pointer to allocated + * a1 Upper 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated. - * a2 Lower 32bits of 64bit physical pointer to allocated + * a2 Lower 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated * a3 Preserved - * a4 Upper 32bits of 64bit Shared memory cookie used when freeing + * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC - * a5 Lower 32bits of 64bit Shared memory cookie used when freeing + * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC * a6-7 Preserved */ @@ -363,9 +389,9 @@ struct optee_smc_disable_shm_cache_result { * * "Call" register usage: * a0 This value, OPTEE_SMC_RETURN_RPC_FREE - * a1 Upper 32bits of 64bit shared memory cookie belonging to this + * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this * argument memory - * a2 Lower 32bits of 64bit shared memory cookie belonging to this + * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this * argument memory * a3-7 Resume information, must be preserved * @@ -379,7 +405,7 @@ struct optee_smc_disable_shm_cache_result { OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE) /* - * Deliver foreign interrupt to normal world. + * Deliver a foreign interrupt in normal world. * * "Call" register usage: * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR @@ -389,7 +415,7 @@ struct optee_smc_disable_shm_cache_result { * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. * a1-7 Preserved */ -#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4 +#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4 #define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR) @@ -405,10 +431,10 @@ struct optee_smc_disable_shm_cache_result { * * "Call" register usage: * a0 OPTEE_SMC_RETURN_RPC_CMD - * a1 Upper 32bit of a 64bit Shared memory cookie holding a + * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated - * a2 Lower 32bit of a 64bit Shared memory cookie holding a + * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated * a3-7 Resume information, must be preserved diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 1e3614e4798f..a0c30b664e53 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -12,6 +12,7 @@ #include #include "optee_private.h" #include "optee_smc.h" +#include "optee_rpc_cmd.h" struct wq_entry { struct list_head link; @@ -89,7 +90,7 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, if (!client.adapter) goto bad; - if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) { + if (params[1].u.value.a & OPTEE_RPC_I2C_FLAGS_TEN_BIT) { if (!i2c_check_functionality(client.adapter, I2C_FUNC_10BIT_ADDR)) { i2c_put_adapter(client.adapter); @@ -103,11 +104,11 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, snprintf(client.name, I2C_NAME_SIZE, "i2c%d", client.adapter->nr); switch (params[0].u.value.a) { - case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD: + case OPTEE_RPC_I2C_TRANSFER_RD: ret = i2c_master_recv(&client, params[2].u.memref.shm->kaddr, params[2].u.memref.size); break; - case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR: + case OPTEE_RPC_I2C_TRANSFER_WR: ret = i2c_master_send(&client, params[2].u.memref.shm->kaddr, params[2].u.memref.size); break; @@ -194,10 +195,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee, goto bad; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP: + case OPTEE_RPC_WAIT_QUEUE_SLEEP: wq_sleep(&optee->wait_queue, arg->params[0].u.value.b); break; - case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP: + case OPTEE_RPC_WAIT_QUEUE_WAKEUP: wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b); break; default: @@ -267,11 +268,11 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) struct tee_shm *shm; param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; - param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; + param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL; param.u.value.b = sz; param.u.value.c = 0; - ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m); + ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m); if (ret) return ERR_PTR(-ENOMEM); @@ -308,10 +309,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, sz = arg->params[0].u.value.b; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_SHM_TYPE_APPL: + case OPTEE_RPC_SHM_TYPE_APPL: shm = cmd_alloc_suppl(ctx, sz); break; - case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: + case OPTEE_RPC_SHM_TYPE_KERNEL: shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED); break; default: @@ -383,7 +384,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) struct tee_param param; param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; - param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; + param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL; param.u.value.b = tee_shm_get_id(shm); param.u.value.c = 0; @@ -400,7 +401,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) */ tee_shm_put(shm); - optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m); + optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m); } static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, @@ -418,10 +419,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_SHM_TYPE_APPL: + case OPTEE_RPC_SHM_TYPE_APPL: cmd_free_suppl(ctx, shm); break; - case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: + case OPTEE_RPC_SHM_TYPE_KERNEL: tee_shm_free(shm); break; default: @@ -458,23 +459,23 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, } switch (arg->cmd) { - case OPTEE_MSG_RPC_CMD_GET_TIME: + case OPTEE_RPC_CMD_GET_TIME: handle_rpc_func_cmd_get_time(arg); break; - case OPTEE_MSG_RPC_CMD_WAIT_QUEUE: + case OPTEE_RPC_CMD_WAIT_QUEUE: handle_rpc_func_cmd_wq(optee, arg); break; - case OPTEE_MSG_RPC_CMD_SUSPEND: + case OPTEE_RPC_CMD_SUSPEND: handle_rpc_func_cmd_wait(arg); break; - case OPTEE_MSG_RPC_CMD_SHM_ALLOC: + case OPTEE_RPC_CMD_SHM_ALLOC: free_pages_list(call_ctx); handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); break; - case OPTEE_MSG_RPC_CMD_SHM_FREE: + case OPTEE_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); break; - case OPTEE_MSG_RPC_CMD_I2C_TRANSFER: + case OPTEE_RPC_CMD_I2C_TRANSFER: handle_rpc_func_cmd_i2c_transfer(ctx, arg); break; default: -- cgit v1.2.3 From 01f937ffc4686837d6c43dea80c6ade6cbd2940a Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 30 Jan 2021 15:23:49 +0100 Subject: soc: qcom: ocmem: don't return NULL in of_get_ocmem If ocmem probe fails for whatever reason, of_get_ocmem returned NULL. Without this, users must check for both NULL and IS_ERR on the returned pointer - which didn't happen in drivers/gpu/drm/msm/adreno/adreno_gpu.c leading to a NULL pointer dereference. Reviewed-by: Brian Masney Fixes: 88c1e9404f1d ("soc: qcom: add OCMEM driver") Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20210130142349.53335-1-luca@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 7f9e9944d1ea..f1875dc31ae2 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -189,6 +189,7 @@ struct ocmem *of_get_ocmem(struct device *dev) { struct platform_device *pdev; struct device_node *devnode; + struct ocmem *ocmem; devnode = of_parse_phandle(dev->of_node, "sram", 0); if (!devnode || !devnode->parent) { @@ -202,7 +203,12 @@ struct ocmem *of_get_ocmem(struct device *dev) return ERR_PTR(-EPROBE_DEFER); } - return platform_get_drvdata(pdev); + ocmem = platform_get_drvdata(pdev); + if (!ocmem) { + dev_err(dev, "Cannot get ocmem\n"); + return ERR_PTR(-ENODEV); + } + return ocmem; } EXPORT_SYMBOL(of_get_ocmem); -- cgit v1.2.3 From 958567600517fd15b7f35ca1a8be0104f0eb0686 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Mon, 25 Jan 2021 10:36:57 +0100 Subject: tee: optee: remove need_resched() before cond_resched() Testing need_resched() before cond_resched() is not needed as an equivalent test is done internally in cond_resched(). So drop the need_resched() test. Fixes: dcb3b06d9c34 ("tee: optee: replace might_sleep with cond_resched") Reviewed-by: Rouven Czerwinski Tested-by: Rouven Czerwinski Tested-by: Sumit Garg Acked-by: Arnd Bergmann Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 780d7c4fd756..7a77e375b503 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -149,8 +149,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) */ optee_cq_wait_for_completion(&optee->call_queue, &w); } else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) { - if (need_resched()) - cond_resched(); + cond_resched(); param.a0 = res.a0; param.a1 = res.a1; param.a2 = res.a2; -- cgit v1.2.3 From 7deff441f53cc148cbf18381bd252a754b0d7d4e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Feb 2021 16:49:25 +0100 Subject: drivers: soc: atmel: fix type for same7 A missing comma caused a build failure: drivers/soc/atmel/soc.c:196:24: error: too few arguments provided to function-like macro invocation Fixes: af3a10513cd6 ("drivers: soc: atmel: add per soc id and version match masks") Signed-off-by: Arnd Bergmann Acked-by: Alexandre Belloni Signed-off-by: Arnd Bergmann --- drivers/soc/atmel/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index a2967846809f..a490ad7e090f 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -191,7 +191,7 @@ static const struct at91_soc socs[] __initconst = { AT91_SOC(SAME70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, AT91_CIDR_VERSION_MASK, SAME70Q20_EXID_MATCH, "same70q20", "same7"), - AT91_SOC(SAME70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK + AT91_SOC(SAME70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, AT91_CIDR_VERSION_MASK, SAME70Q19_EXID_MATCH, "same70q19", "same7"), AT91_SOC(SAMS70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, -- cgit v1.2.3 From 67bc809752796acb2641ca343cad5b45eef31d7c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2021 12:37:52 +0100 Subject: optee: simplify i2c access Storing a bogus i2c_client structure on the stack adds overhead and causes a compile-time warning: drivers/tee/optee/rpc.c:493:6: error: stack frame size of 1056 bytes in function 'optee_handle_rpc' [-Werror,-Wframe-larger-than=] void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, Change the implementation of handle_rpc_func_cmd_i2c_transfer() to open-code the i2c_transfer() call, which makes it easier to read and avoids the warning. Fixes: c05210ab9757 ("drivers: optee: allow op-tee to access devices on the i2c bus") Tested-by: Jorge Ramirez-Ortiz Signed-off-by: Arnd Bergmann Signed-off-by: Jens Wiklander --- drivers/tee/optee/rpc.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 1e3614e4798f..6cbb3643c6c4 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -54,8 +54,9 @@ bad: static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, struct optee_msg_arg *arg) { - struct i2c_client client = { 0 }; struct tee_param *params; + struct i2c_adapter *adapter; + struct i2c_msg msg = { }; size_t i; int ret = -EOPNOTSUPP; u8 attr[] = { @@ -85,48 +86,48 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, goto bad; } - client.adapter = i2c_get_adapter(params[0].u.value.b); - if (!client.adapter) + adapter = i2c_get_adapter(params[0].u.value.b); + if (!adapter) goto bad; if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) { - if (!i2c_check_functionality(client.adapter, + if (!i2c_check_functionality(adapter, I2C_FUNC_10BIT_ADDR)) { - i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); goto bad; } - client.flags = I2C_CLIENT_TEN; + msg.flags = I2C_M_TEN; } - client.addr = params[0].u.value.c; - snprintf(client.name, I2C_NAME_SIZE, "i2c%d", client.adapter->nr); + msg.addr = params[0].u.value.c; + msg.buf = params[2].u.memref.shm->kaddr; + msg.len = params[2].u.memref.size; switch (params[0].u.value.a) { case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD: - ret = i2c_master_recv(&client, params[2].u.memref.shm->kaddr, - params[2].u.memref.size); + msg.flags |= I2C_M_RD; break; case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR: - ret = i2c_master_send(&client, params[2].u.memref.shm->kaddr, - params[2].u.memref.size); break; default: - i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); goto bad; } + ret = i2c_transfer(adapter, &msg, 1); + if (ret < 0) { arg->ret = TEEC_ERROR_COMMUNICATION; } else { - params[3].u.value.a = ret; + params[3].u.value.a = msg.len; if (optee_to_msg_param(arg->params, arg->num_params, params)) arg->ret = TEEC_ERROR_BAD_PARAMETERS; else arg->ret = TEEC_SUCCESS; } - i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); kfree(params); return; bad: -- cgit v1.2.3 From 62c290a6784af56fa1438f6d2688cd9360c840f1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 6 Feb 2021 12:13:43 +0100 Subject: memory: ti-emif-pm: Drop of_match_ptr from of_device_id table The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might be not relevant here). This fixes compile warning (!CONFIG_OF with clang): drivers/memory/ti-emif-pm.c:238:34: warning: unused variable 'ti_emif_of_match' [-Wunused-const-variable] Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/r/20210206111343.19273-1-krzk@kernel.org --- drivers/memory/ti-emif-pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c index 6c747c1e98cb..179fec2da56d 100644 --- a/drivers/memory/ti-emif-pm.c +++ b/drivers/memory/ti-emif-pm.c @@ -340,7 +340,7 @@ static struct platform_driver ti_emif_driver = { .remove = ti_emif_remove, .driver = { .name = KBUILD_MODNAME, - .of_match_table = of_match_ptr(ti_emif_of_match), + .of_match_table = ti_emif_of_match, .pm = &ti_emif_pm_ops, }, }; -- cgit v1.2.3 From 0e9bc42089a7374d056745419c7a8f28016b4191 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 6 Feb 2021 12:17:15 +0100 Subject: memory: samsung: exynos5422-dmc: Correct function names in kerneldoc Correct kerneldoc to fix W=1 warnings: drivers/memory/samsung/exynos5422-dmc.c:290: warning: expecting prototype for find_target_freq_id(). Prototype was for find_target_freq_idx() instead drivers/memory/samsung/exynos5422-dmc.c:1015: warning: expecting prototype for exynos5_dmc_align_initial_frequency(). Prototype was for exynos5_dmc_align_init_freq() instead Signed-off-by: Krzysztof Kozlowski Reviewed-by: Lukasz Luba Link: https://lore.kernel.org/r/20210206111715.20774-1-krzk@kernel.org --- drivers/memory/samsung/exynos5422-dmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index c5ee4121a4d2..1dabb509dec3 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -278,7 +278,7 @@ static int exynos5_counters_disable_edev(struct exynos5_dmc *dmc) } /** - * find_target_freq_id() - Finds requested frequency in local DMC configuration + * find_target_freq_idx() - Finds requested frequency in local DMC configuration * @dmc: device for which the information is checked * @target_rate: requested frequency in KHz * @@ -998,7 +998,7 @@ static struct devfreq_dev_profile exynos5_dmc_df_profile = { }; /** - * exynos5_dmc_align_initial_frequency() - Align initial frequency value + * exynos5_dmc_align_init_freq() - Align initial frequency value * @dmc: device for which the frequency is going to be set * @bootloader_init_freq: initial frequency set by the bootloader in KHz * -- cgit v1.2.3 From 321b36c79c431957c8c599a9f9640096c305cd03 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Sun, 7 Feb 2021 16:02:50 +0800 Subject: memory: tegra186-emc: Replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE Fix the following coccicheck warning: drivers/memory/tegra/tegra186-emc.c:158:0-23: WARNING: tegra186_emc_debug_max_rate_fops should be defined with DEFINE_DEBUGFS_ATTRIBUTE. Signed-off-by: Jiapeng Chong Link: https://lore.kernel.org/r/1612684970-125948-1-git-send-email-jiapeng.chong@linux.alibaba.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra186-emc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index fa8af17b0e2d..d65e7c2a580b 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -125,9 +125,9 @@ static int tegra186_emc_debug_min_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra186_emc_debug_min_rate_fops, - tegra186_emc_debug_min_rate_get, - tegra186_emc_debug_min_rate_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_min_rate_fops, + tegra186_emc_debug_min_rate_get, + tegra186_emc_debug_min_rate_set, "%llu\n"); static int tegra186_emc_debug_max_rate_get(void *data, u64 *rate) { @@ -155,9 +155,9 @@ static int tegra186_emc_debug_max_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, - tegra186_emc_debug_max_rate_get, - tegra186_emc_debug_max_rate_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, + tegra186_emc_debug_max_rate_get, + tegra186_emc_debug_max_rate_set, "%llu\n"); static int tegra186_emc_probe(struct platform_device *pdev) { -- cgit v1.2.3 From 3f94cf15583be554df7aaa651b8ff8e1b68fbe51 Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo Date: Tue, 8 Dec 2020 17:17:47 +0800 Subject: soc: aspeed: snoop: Add clock control logic If LPC SNOOP driver is registered ahead of lpc-ctrl module, LPC SNOOP block will be enabled without heart beating of LCLK until lpc-ctrl enables the LCLK. This issue causes improper handling on host interrupts when the host sends interrupt in that time frame. Then kernel eventually forcibly disables the interrupt with dumping stack and printing a 'nobody cared this irq' message out. To prevent this issue, all LPC sub-nodes should enable LCLK individually so this patch adds clock control logic into the LPC SNOOP driver. Fixes: 3772e5da4454 ("drivers/misc: Aspeed LPC snoop output using misc chardev") Signed-off-by: Jae Hyun Yoo Signed-off-by: Vernon Mauery Signed-off-by: John Wang Reviewed-by: Joel Stanley Link: https://lore.kernel.org/r/20201208091748.1920-1-wangzhiqiang.bj@bytedance.com Signed-off-by: Joel Stanley --- drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index 682ba0eb4eba..20acac6342ef 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel { struct aspeed_lpc_snoop { struct regmap *regmap; int irq; + struct clk *clk; struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; }; @@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) return -ENODEV; } + lpc_snoop->clk = devm_clk_get(dev, NULL); + if (IS_ERR(lpc_snoop->clk)) { + rc = PTR_ERR(lpc_snoop->clk); + if (rc != -EPROBE_DEFER) + dev_err(dev, "couldn't get clock\n"); + return rc; + } + rc = clk_prepare_enable(lpc_snoop->clk); + if (rc) { + dev_err(dev, "couldn't enable clock\n"); + return rc; + } + rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev); if (rc) - return rc; + goto err; rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) - return rc; + goto err; /* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); - if (rc) + if (rc) { aspeed_lpc_disable_snoop(lpc_snoop, 0); + goto err; + } } + return 0; + +err: + clk_disable_unprepare(lpc_snoop->clk); + return rc; } @@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) aspeed_lpc_disable_snoop(lpc_snoop, 0); aspeed_lpc_disable_snoop(lpc_snoop, 1); + clk_disable_unprepare(lpc_snoop->clk); + return 0; } -- cgit v1.2.3 From d0e72be77e7995923fac73f27cf7a75d3d1a4dec Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 10 Feb 2021 22:16:51 +1030 Subject: soc: aspeed: socinfo: Add new systems Aspeed's u-boot sdk has been updated with the SoC IDs for the AST2605 variant, as well as A2 and A3 variants of the 2600 family. >From u-boot's arch/arm/mach-aspeed/ast2600/scu_info.c: SOC_ID("AST2600-A0", 0x0500030305000303), SOC_ID("AST2600-A1", 0x0501030305010303), SOC_ID("AST2620-A1", 0x0501020305010203), SOC_ID("AST2600-A2", 0x0502030305010303), SOC_ID("AST2620-A2", 0x0502020305010203), SOC_ID("AST2605-A2", 0x0502010305010103), SOC_ID("AST2600-A3", 0x0503030305030303), SOC_ID("AST2620-A3", 0x0503020305030203), SOC_ID("AST2605-A3", 0x0503010305030103), Fixes: e0218dca5787 ("soc: aspeed: Add soc info driver") Link: https://lore.kernel.org/r/20210210114651.334324-1-joel@jms.id.au Signed-off-by: Joel Stanley --- drivers/soc/aspeed/aspeed-socinfo.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c index 773930e0cb10..e3215f826d17 100644 --- a/drivers/soc/aspeed/aspeed-socinfo.c +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -25,6 +25,7 @@ static struct { /* AST2600 */ { "AST2600", 0x05000303 }, { "AST2620", 0x05010203 }, + { "AST2605", 0x05030103 }, }; static const char *siliconid_to_name(u32 siliconid) @@ -43,14 +44,30 @@ static const char *siliconid_to_name(u32 siliconid) static const char *siliconid_to_rev(u32 siliconid) { unsigned int rev = (siliconid >> 16) & 0xff; - - switch (rev) { - case 0: - return "A0"; - case 1: - return "A1"; - case 3: - return "A2"; + unsigned int gen = (siliconid >> 24) & 0xff; + + if (gen < 0x5) { + /* AST2500 and below */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 3: + return "A2"; + } + } else { + /* AST2600 */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 2: + return "A2"; + case 3: + return "A3"; + } } return "??"; -- cgit v1.2.3