From d94436465152465555c8e5efbe611db40c9749f7 Mon Sep 17 00:00:00 2001 From: Stefan Kristiansson Date: Thu, 11 May 2023 16:20:48 +0300 Subject: soc/tegra: fuse: Add support for Tegra264 Add support for Tegra264 to the fuse handling code. Signed-off-by: Stefan Kristiansson Signed-off-by: Peter De Schrijver Signed-off-by: Thierry Reding --- include/soc/tegra/fuse.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index a63de5da8124..3a513be50243 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2023, NVIDIA CORPORATION. All rights reserved. */ #ifndef __SOC_TEGRA_FUSE_H__ @@ -17,6 +17,7 @@ #define TEGRA186 0x18 #define TEGRA194 0x19 #define TEGRA234 0x23 +#define TEGRA264 0x26 #define TEGRA_FUSE_SKU_CALIB_0 0xf0 #define TEGRA30_FUSE_SATA_CALIB 0x124 -- cgit v1.2.3 From 9a38cb27668e275ed912e67388cf11f454a24cc6 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 11 May 2023 23:02:04 +0530 Subject: memory: tegra: Add interconnect support for DRAM scaling in Tegra234 Add Interconnect framework support to dynamically set the DRAM bandwidth from different clients. Both the MC and EMC drivers are added as ICC providers. The path for any request is: MC-Client[1-n] -> MC -> EMC -> EMEM/DRAM MC client's request for bandwidth will go to the MC driver which passes the client request info like BPMP Client ID, Client type and the Bandwidth to the BPMP-FW. The final DRAM freq to achieve the requested bandwidth is set by the BPMP-FW based on the passed parameters. Signed-off-by: Sumit Gupta Acked-by: Krzysztof Kozlowski Signed-off-by: Thierry Reding --- drivers/memory/tegra/mc.c | 5 ++ drivers/memory/tegra/tegra186-emc.c | 133 ++++++++++++++++++++++++++++++++++ drivers/memory/tegra/tegra234.c | 138 +++++++++++++++++++++++++++++++++++- include/linux/tegra-icc.h | 65 +++++++++++++++++ include/soc/tegra/mc.h | 7 ++ 5 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 include/linux/tegra-icc.h (limited to 'include') diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 9082b6c3763d..983455b1f98d 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) mc->provider.data = &mc->provider; mc->provider.set = mc->soc->icc_ops->set; mc->provider.aggregate = mc->soc->icc_ops->aggregate; + mc->provider.get_bw = mc->soc->icc_ops->get_bw; + mc->provider.xlate = mc->soc->icc_ops->xlate; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; icc_provider_init(&mc->provider); @@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) err = icc_link_create(node, TEGRA_ICC_MC); if (err) goto remove_nodes; + + node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]); } err = icc_provider_register(&mc->provider); diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index e935ad4e95b6..6ad8a4023dd7 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -7,9 +7,11 @@ #include #include #include +#include #include #include +#include "mc.h" struct tegra186_emc_dvfs { unsigned long latency; @@ -29,8 +31,15 @@ struct tegra186_emc { unsigned long min_rate; unsigned long max_rate; } debugfs; + + struct icc_provider provider; }; +static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider) +{ + return container_of(provider, struct tegra186_emc, provider); +} + /* * debugfs interface * @@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, tegra186_emc_debug_max_rate_get, tegra186_emc_debug_max_rate_set, "%llu\n"); +/* + * tegra_emc_icc_set_bw() - Set BW api for EMC provider + * @src: ICC node for External Memory Controller (EMC) + * @dst: ICC node for External Memory (DRAM) + * + * Do nothing here as info to BPMP-FW is now passed in the BW set function + * of the MC driver. BPMP-FW sets the final Freq based on the passed values. + */ +static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst) +{ + return 0; +} + +static struct icc_node * +tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data) +{ + struct icc_provider *provider = data; + 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; + + return node; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) +{ + *avg = 0; + *peak = 0; + + return 0; +} + +static int tegra_emc_interconnect_init(struct tegra186_emc *emc) +{ + struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent); + const struct tegra_mc_soc *soc = mc->soc; + struct icc_node *node; + int err; + + emc->provider.dev = emc->dev; + emc->provider.set = tegra_emc_icc_set_bw; + emc->provider.data = &emc->provider; + emc->provider.aggregate = soc->icc_ops->aggregate; + emc->provider.xlate = tegra_emc_of_icc_xlate; + emc->provider.get_bw = tegra_emc_icc_get_init_bw; + + icc_provider_init(&emc->provider); + + /* create External Memory Controller node */ + node = icc_node_create(TEGRA_ICC_EMC); + if (IS_ERR(node)) { + err = PTR_ERR(node); + goto err_msg; + } + + 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); + + err = icc_provider_register(&emc->provider); + if (err) + goto remove_nodes; + + return 0; + +remove_nodes: + icc_nodes_remove(&emc->provider); +err_msg: + dev_err(emc->dev, "failed to initialize ICC: %d\n", err); + + return err; +} + static int tegra186_emc_probe(struct platform_device *pdev) { + struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct mrq_emc_dvfs_latency_response response; struct tegra_bpmp_message msg; struct tegra186_emc *emc; @@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev) debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, emc, &tegra186_emc_debug_max_rate_fops); + if (mc && mc->soc->icc_ops) { + if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) { + mc->bwmgr_mrq_supported = true; + + /* + * MC driver probe can't get BPMP reference as it gets probed + * earlier than BPMP. So, save the BPMP ref got from the EMC + * DT node in the mc->bpmp and use it in MC's icc_set hook. + */ + mc->bpmp = emc->bpmp; + barrier(); + } + + /* + * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'. + * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return + * EINVAL instead of passing the request to BPMP-FW later when the BW + * request is made by client with 'icc_set_bw()' call. + */ + err = tegra_emc_interconnect_init(emc); + if (err) { + mc->bpmp = NULL; + goto put_bpmp; + } + } + return 0; put_bpmp: @@ -245,9 +374,12 @@ put_bpmp: static int tegra186_emc_remove(struct platform_device *pdev) { + struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct tegra186_emc *emc = platform_get_drvdata(pdev); debugfs_remove_recursive(emc->debugfs.root); + + mc->bpmp = NULL; tegra_bpmp_put(emc->bpmp); return 0; @@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = { .name = "tegra186-emc", .of_match_table = tegra186_emc_of_match, .suppress_bind_attrs = true, + .sync_state = icc_sync_state, }, .probe = tegra186_emc_probe, .remove = tegra186_emc_remove, diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 02dcc5748bba..56d911926d54 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1,18 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. */ #include #include +#include +#include +#include #include "mc.h" static const struct tegra_mc_client tegra234_mc_clients[] = { { .id = TEGRA234_MEMORY_CLIENT_MGBEARD, .name = "mgbeard", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE, .regs = { .sid = { @@ -23,6 +28,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBRD, .name = "mgbebrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { @@ -33,6 +40,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECRD, .name = "mgbecrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { @@ -43,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDRD, .name = "mgbedrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { @@ -52,6 +63,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEAWR, + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .name = "mgbeawr", .sid = TEGRA234_SID_MGBE, .regs = { @@ -63,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBWR, .name = "mgbebwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { @@ -73,6 +88,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECWR, .name = "mgbecwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { @@ -83,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB, .name = "sdmmcrab", + .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { @@ -93,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDWR, .name = "mgbedwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { @@ -103,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB, .name = "sdmmcwab", + .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { @@ -153,6 +176,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAR, .name = "apedmar", + .bpmp_id = TEGRA_ICC_BPMP_APEDMA, + .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { @@ -163,6 +188,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAW, .name = "apedmaw", + .bpmp_id = TEGRA_ICC_BPMP_APEDMA, + .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { @@ -333,6 +360,114 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, }; +/* + * tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW + * @src: ICC node for Memory Controller's (MC) Client + * @dst: ICC node for Memory Controller (MC) + * + * Passing the current request info from the MC to the BPMP-FW where + * LA and PTSA registers are accessed and the final EMC freq is set + * based on client_id, type, latency and bandwidth. + * icc_set_bw() makes set_bw calls for both MC and EMC providers in + * sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'. + * So, the data passed won't be updated by concurrent set calls from + * other clients. + */ +static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider); + struct mrq_bwmgr_int_request bwmgr_req = { 0 }; + struct mrq_bwmgr_int_response bwmgr_resp = { 0 }; + const struct tegra_mc_client *pclient = src->data; + struct tegra_bpmp_message msg; + int ret; + + /* + * Same Src and Dst node will happen during boot from icc_node_add(). + * This can be used to pre-initialize and set bandwidth for all clients + * before their drivers are loaded. We are skipping this case as for us, + * the pre-initialization already happened in Bootloader(MB2) and BPMP-FW. + */ + if (src->id == dst->id) + return 0; + + if (!mc->bwmgr_mrq_supported) + return -EINVAL; + + if (!mc->bpmp) { + dev_err(mc->dev, "BPMP reference NULL\n"); + return -ENOENT; + } + + if (pclient->type == TEGRA_ICC_NISO) + bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw; + else + bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw; + + bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id; + + bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET; + bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw; + bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS; + + memset(&msg, 0, sizeof(msg)); + msg.mrq = MRQ_BWMGR_INT; + msg.tx.data = &bwmgr_req; + msg.tx.size = sizeof(bwmgr_req); + msg.rx.data = &bwmgr_resp; + msg.rx.size = sizeof(bwmgr_resp); + + ret = tegra_bpmp_transfer(mc->bpmp, &msg); + if (ret < 0) { + dev_err(mc->dev, "BPMP transfer failed: %d\n", ret); + goto error; + } + if (msg.rx.ret < 0) { + pr_err("failed to set bandwidth for %u: %d\n", + bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret); + ret = -EINVAL; + } + +error: + return ret; +} + +static struct icc_node* +tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) +{ + struct tegra_mc *mc = icc_provider_to_tegra_mc(data); + unsigned int cl_id = spec->args[0]; + struct icc_node *node; + + list_for_each_entry(node, &mc->provider.nodes, node_list) { + if (node->id != cl_id) + continue; + + return node; + } + + /* + * If a client driver calls devm_of_icc_get() before the MC driver + * is probed, then return EPROBE_DEFER to the client driver. + */ + return ERR_PTR(-EPROBE_DEFER); +} + +static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) +{ + *avg = 0; + *peak = 0; + + return 0; +} + +static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { + .xlate = tegra234_mc_of_icc_xlate, + .aggregate = icc_std_aggregate, + .get_bw = tegra234_mc_icc_get_init_bw, + .set = tegra234_mc_icc_set, +}; + const struct tegra_mc_soc tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, @@ -345,6 +480,7 @@ const struct tegra_mc_soc tegra234_mc_soc = { MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, + .icc_ops = &tegra234_mc_icc_ops, .ch_intmask = 0x0000ff00, .global_intstatus_channel_shift = 8, /* diff --git a/include/linux/tegra-icc.h b/include/linux/tegra-icc.h new file mode 100644 index 000000000000..4b4d4bee290c --- /dev/null +++ b/include/linux/tegra-icc.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022-2023 NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef LINUX_TEGRA_ICC_H +#define LINUX_TEGRA_ICC_H + +enum tegra_icc_client_type { + TEGRA_ICC_NONE, + TEGRA_ICC_NISO, + TEGRA_ICC_ISO_DISPLAY, + TEGRA_ICC_ISO_VI, + TEGRA_ICC_ISO_AUDIO, + TEGRA_ICC_ISO_VIFAL, +}; + +/* ICC ID's for MC client's used in BPMP */ +#define TEGRA_ICC_BPMP_DEBUG 1 +#define TEGRA_ICC_BPMP_CPU_CLUSTER0 2 +#define TEGRA_ICC_BPMP_CPU_CLUSTER1 3 +#define TEGRA_ICC_BPMP_CPU_CLUSTER2 4 +#define TEGRA_ICC_BPMP_GPU 5 +#define TEGRA_ICC_BPMP_CACTMON 6 +#define TEGRA_ICC_BPMP_DISPLAY 7 +#define TEGRA_ICC_BPMP_VI 8 +#define TEGRA_ICC_BPMP_EQOS 9 +#define TEGRA_ICC_BPMP_PCIE_0 10 +#define TEGRA_ICC_BPMP_PCIE_1 11 +#define TEGRA_ICC_BPMP_PCIE_2 12 +#define TEGRA_ICC_BPMP_PCIE_3 13 +#define TEGRA_ICC_BPMP_PCIE_4 14 +#define TEGRA_ICC_BPMP_PCIE_5 15 +#define TEGRA_ICC_BPMP_PCIE_6 16 +#define TEGRA_ICC_BPMP_PCIE_7 17 +#define TEGRA_ICC_BPMP_PCIE_8 18 +#define TEGRA_ICC_BPMP_PCIE_9 19 +#define TEGRA_ICC_BPMP_PCIE_10 20 +#define TEGRA_ICC_BPMP_DLA_0 21 +#define TEGRA_ICC_BPMP_DLA_1 22 +#define TEGRA_ICC_BPMP_SDMMC_1 23 +#define TEGRA_ICC_BPMP_SDMMC_2 24 +#define TEGRA_ICC_BPMP_SDMMC_3 25 +#define TEGRA_ICC_BPMP_SDMMC_4 26 +#define TEGRA_ICC_BPMP_NVDEC 27 +#define TEGRA_ICC_BPMP_NVENC 28 +#define TEGRA_ICC_BPMP_NVJPG_0 29 +#define TEGRA_ICC_BPMP_NVJPG_1 30 +#define TEGRA_ICC_BPMP_OFAA 31 +#define TEGRA_ICC_BPMP_XUSB_HOST 32 +#define TEGRA_ICC_BPMP_XUSB_DEV 33 +#define TEGRA_ICC_BPMP_TSEC 34 +#define TEGRA_ICC_BPMP_VIC 35 +#define TEGRA_ICC_BPMP_APE 36 +#define TEGRA_ICC_BPMP_APEDMA 37 +#define TEGRA_ICC_BPMP_SE 38 +#define TEGRA_ICC_BPMP_ISP 39 +#define TEGRA_ICC_BPMP_HDA 40 +#define TEGRA_ICC_BPMP_VIFAL 41 +#define TEGRA_ICC_BPMP_VI2FAL 42 +#define TEGRA_ICC_BPMP_VI2 43 +#define TEGRA_ICC_BPMP_RCE 44 +#define TEGRA_ICC_BPMP_PVA 45 + +#endif /* LINUX_TEGRA_ICC_H */ diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 51a2263e1bc5..900d88b26fae 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -13,6 +13,7 @@ #include #include #include +#include struct clk; struct device; @@ -26,6 +27,8 @@ struct tegra_mc_timing { struct tegra_mc_client { unsigned int id; + unsigned int bpmp_id; + enum tegra_icc_client_type type; const char *name; /* * For Tegra210 and earlier, this is the SWGROUP ID used for IOVA translations in the @@ -166,8 +169,10 @@ struct tegra_mc_icc_ops { int (*set)(struct icc_node *src, struct icc_node *dst); int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak); + struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data); struct icc_node_data *(*xlate_extended)(struct of_phandle_args *spec, void *data); + int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak); }; struct tegra_mc_ops { @@ -214,6 +219,7 @@ struct tegra_mc_soc { }; struct tegra_mc { + struct tegra_bpmp *bpmp; struct device *dev; struct tegra_smmu *smmu; struct gart_device *gart; @@ -229,6 +235,7 @@ struct tegra_mc { struct tegra_mc_timing *timings; unsigned int num_timings; + bool bwmgr_mrq_supported; struct reset_controller_dev reset; struct icc_provider provider; -- cgit v1.2.3 From e852af72a7f21f4d25994365af86a92438d68014 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 11 May 2023 23:02:08 +0530 Subject: memory: tegra: Make CPU cluster BW request a multiple of MC channels Make CPU cluster's bandwidth (BW) request a multiple of MC channels. CPU OPP tables have BW info per MC channel. But, the actual BW depends on the number of MC channels which can change as per the boot config. Get the number of MC channels which are actually enabled in current boot configuration and multiply the BW request from a CPU cluster with the number of enabled MC channels. This is not required to be done for other MC clients. Signed-off-by: Sumit Gupta Acked-by: Krzysztof Kozlowski Signed-off-by: Thierry Reding --- drivers/memory/tegra/mc.c | 19 +++++++++++++++++++ drivers/memory/tegra/mc.h | 1 + drivers/memory/tegra/tegra234.c | 24 +++++++++++++++++++++++- include/soc/tegra/mc.h | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 983455b1f98d..4a750da1c12a 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -843,6 +843,23 @@ remove_nodes: return err; } +static void tegra_mc_num_channel_enabled(struct tegra_mc *mc) +{ + unsigned int i; + u32 value; + + value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE); + if (value <= 0) { + mc->num_channels = mc->soc->num_channels; + return; + } + + for (i = 0; i < 32; i++) { + if (value & BIT(i)) + mc->num_channels++; + } +} + static int tegra_mc_probe(struct platform_device *pdev) { struct tegra_mc *mc; @@ -881,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev) return err; } + tegra_mc_num_channel_enabled(mc); + if (mc->soc->ops && mc->soc->ops->handle_irq) { mc->irq = platform_get_irq(pdev, 0); if (mc->irq < 0) diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index bc01586b6560..c3f6655bec60 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -53,6 +53,7 @@ #define MC_ERR_ROUTE_SANITY_ADR 0x9c4 #define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 #define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8 #define MC_GLOBAL_INTSTATUS 0xf24 #define MC_ERR_ADR_HI 0x11fc diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 0fa68862749f..8e873a7bc34f 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -867,6 +867,28 @@ error: return ret; } +static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + struct icc_provider *p = node->provider; + struct tegra_mc *mc = icc_provider_to_tegra_mc(p); + + if (!mc->bwmgr_mrq_supported) + return -EINVAL; + + if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || + node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || + node->id == TEGRA_ICC_MC_CPU_CLUSTER2) { + if (mc) + peak_bw = peak_bw * mc->num_channels; + } + + *agg_avg += avg_bw; + *agg_peak = max(*agg_peak, peak_bw); + + return 0; +} + static struct icc_node* tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) { @@ -898,7 +920,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { .xlate = tegra234_mc_of_icc_xlate, - .aggregate = icc_std_aggregate, + .aggregate = tegra234_mc_icc_aggregate, .get_bw = tegra234_mc_icc_get_init_bw, .set = tegra234_mc_icc_set, }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 900d88b26fae..fc3001483e62 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -234,6 +234,7 @@ struct tegra_mc { struct tegra_mc_timing *timings; unsigned int num_timings; + unsigned int num_channels; bool bwmgr_mrq_supported; struct reset_controller_dev reset; -- cgit v1.2.3 From 67d1b0a1030fb20d54b720df6e976c06b893fb00 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 14 Apr 2023 10:25:39 +0530 Subject: soc: ti: pruss: Add pruss_get()/put() API Add two new get and put API, pruss_get() and pruss_put() to the PRUSS platform driver to allow client drivers to request a handle to a PRUSS device. This handle will be used by client drivers to request various operations of the PRUSS platform driver through additional API that will be added in the following patches. The pruss_get() function returns the pruss handle corresponding to a PRUSS device referenced by a PRU remoteproc instance. The pruss_put() is the complimentary function to pruss_get(). Co-developed-by: Suman Anna Signed-off-by: Suman Anna Signed-off-by: Tero Kristo Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Acked-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-2-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 18 +++++++++++++ 2 files changed, 80 insertions(+) (limited to 'include') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index e68441bd7b30..f836660dac64 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -6,6 +6,7 @@ * Author(s): * Suman Anna * Andrew F. Davis + * Tero Kristo */ #include @@ -18,6 +19,7 @@ #include #include #include +#include #include /** @@ -30,6 +32,66 @@ struct pruss_private_data { bool has_core_mux_clock; }; +/** + * pruss_get() - get the pruss for a given PRU remoteproc + * @rproc: remoteproc handle of a PRU instance + * + * Finds the parent pruss device for a PRU given the @rproc handle of the + * PRU remote processor. This function increments the pruss device's refcount, + * so always use pruss_put() to decrement it back once pruss isn't needed + * anymore. + * + * This API doesn't check if @rproc is valid or not. It is expected the caller + * will have done a pru_rproc_get() on @rproc, before calling this API to make + * sure that @rproc is valid. + * + * Return: pruss handle on success, and an ERR_PTR on failure using one + * of the following error values + * -EINVAL if invalid parameter + * -ENODEV if PRU device or PRUSS device is not found + */ +struct pruss *pruss_get(struct rproc *rproc) +{ + struct pruss *pruss; + struct device *dev; + struct platform_device *ppdev; + + if (IS_ERR_OR_NULL(rproc)) + return ERR_PTR(-EINVAL); + + dev = &rproc->dev; + + /* make sure it is PRU rproc */ + if (!dev->parent || !is_pru_rproc(dev->parent)) + return ERR_PTR(-ENODEV); + + ppdev = to_platform_device(dev->parent->parent); + pruss = platform_get_drvdata(ppdev); + if (!pruss) + return ERR_PTR(-ENODEV); + + get_device(pruss->dev); + + return pruss; +} +EXPORT_SYMBOL_GPL(pruss_get); + +/** + * pruss_put() - decrement pruss device's usecount + * @pruss: pruss handle + * + * Complimentary function for pruss_get(). Needs to be called + * after the PRUSS is used, and only if the pruss_get() succeeds. + */ +void pruss_put(struct pruss *pruss) +{ + if (IS_ERR_OR_NULL(pruss)) + return; + + put_device(pruss->dev); +} +EXPORT_SYMBOL_GPL(pruss_put); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index ecfded30ed05..cb40c2b31045 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -9,7 +9,9 @@ #ifndef _PRUSS_DRIVER_H_ #define _PRUSS_DRIVER_H_ +#include #include +#include /* * enum pruss_mem - PRUSS memory range identifiers @@ -51,4 +53,20 @@ struct pruss { struct clk *iep_clk_mux; }; +#if IS_ENABLED(CONFIG_TI_PRUSS) + +struct pruss *pruss_get(struct rproc *rproc); +void pruss_put(struct pruss *pruss); + +#else + +static inline struct pruss *pruss_get(struct rproc *rproc) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline void pruss_put(struct pruss *pruss) { } + +#endif /* CONFIG_TI_PRUSS */ + #endif /* _PRUSS_DRIVER_H_ */ -- cgit v1.2.3 From b789ca1e3380ab63b60c3356c026a7e8eb26ba01 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 14 Apr 2023 10:25:40 +0530 Subject: soc: ti: pruss: Add pruss_{request,release}_mem_region() API Add two new API - pruss_request_mem_region() & pruss_release_mem_region(), to the PRUSS platform driver to allow client drivers to acquire and release the common memory resources present within a PRU-ICSS subsystem. This allows the client drivers to directly manipulate the respective memories, as per their design contract with the associated firmware. Co-developed-by: Suman Anna Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Reviewed-by: Roger Quadros Acked-by: Mathieu Poirier Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-3-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 22 +++++++++++++ 2 files changed, 99 insertions(+) (limited to 'include') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index f836660dac64..df5eb4d959f8 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -92,6 +92,82 @@ void pruss_put(struct pruss *pruss) } EXPORT_SYMBOL_GPL(pruss_put); +/** + * pruss_request_mem_region() - request a memory resource + * @pruss: the pruss instance + * @mem_id: the memory resource id + * @region: pointer to memory region structure to be filled in + * + * This function allows a client driver to request a memory resource, + * and if successful, will let the client driver own the particular + * memory region until released using the pruss_release_mem_region() + * API. + * + * Return: 0 if requested memory region is available (in such case pointer to + * memory region is returned via @region), an error otherwise + */ +int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, + struct pruss_mem_region *region) +{ + if (!pruss || !region || mem_id >= PRUSS_MEM_MAX) + return -EINVAL; + + mutex_lock(&pruss->lock); + + if (pruss->mem_in_use[mem_id]) { + mutex_unlock(&pruss->lock); + return -EBUSY; + } + + *region = pruss->mem_regions[mem_id]; + pruss->mem_in_use[mem_id] = region; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_request_mem_region); + +/** + * pruss_release_mem_region() - release a memory resource + * @pruss: the pruss instance + * @region: the memory region to release + * + * This function is the complimentary function to + * pruss_request_mem_region(), and allows the client drivers to + * release back a memory resource. + * + * Return: 0 on success, an error code otherwise + */ +int pruss_release_mem_region(struct pruss *pruss, + struct pruss_mem_region *region) +{ + int id; + + if (!pruss || !region) + return -EINVAL; + + mutex_lock(&pruss->lock); + + /* find out the memory region being released */ + for (id = 0; id < PRUSS_MEM_MAX; id++) { + if (pruss->mem_in_use[id] == region) + break; + } + + if (id == PRUSS_MEM_MAX) { + mutex_unlock(&pruss->lock); + return -EINVAL; + } + + pruss->mem_in_use[id] = NULL; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_release_mem_region); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; @@ -298,6 +374,7 @@ static int pruss_probe(struct platform_device *pdev) return -ENOMEM; pruss->dev = dev; + mutex_init(&pruss->lock); child = of_get_child_by_name(np, "memories"); if (!child) { diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index cb40c2b31045..c8f2e53b911b 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -9,6 +9,7 @@ #ifndef _PRUSS_DRIVER_H_ #define _PRUSS_DRIVER_H_ +#include #include #include #include @@ -41,6 +42,8 @@ struct pruss_mem_region { * @cfg_base: base iomap for CFG region * @cfg_regmap: regmap for config region * @mem_regions: data for each of the PRUSS memory regions + * @mem_in_use: to indicate if memory resource is in use + * @lock: mutex to serialize access to resources * @core_clk_mux: clk handle for PRUSS CORE_CLK_MUX * @iep_clk_mux: clk handle for PRUSS IEP_CLK_MUX */ @@ -49,6 +52,8 @@ struct pruss { void __iomem *cfg_base; struct regmap *cfg_regmap; struct pruss_mem_region mem_regions[PRUSS_MEM_MAX]; + struct pruss_mem_region *mem_in_use[PRUSS_MEM_MAX]; + struct mutex lock; /* PRU resource lock */ struct clk *core_clk_mux; struct clk *iep_clk_mux; }; @@ -57,6 +62,10 @@ struct pruss { struct pruss *pruss_get(struct rproc *rproc); void pruss_put(struct pruss *pruss); +int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, + struct pruss_mem_region *region); +int pruss_release_mem_region(struct pruss *pruss, + struct pruss_mem_region *region); #else @@ -67,6 +76,19 @@ static inline struct pruss *pruss_get(struct rproc *rproc) static inline void pruss_put(struct pruss *pruss) { } +static inline int pruss_request_mem_region(struct pruss *pruss, + enum pruss_mem mem_id, + struct pruss_mem_region *region) +{ + return -EOPNOTSUPP; +} + +static inline int pruss_release_mem_region(struct pruss *pruss, + struct pruss_mem_region *region) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_TI_PRUSS */ #endif /* _PRUSS_DRIVER_H_ */ -- cgit v1.2.3 From 51b5760e56ef19106a3c4487a66d186d46ccc6f4 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 14 Apr 2023 10:25:41 +0530 Subject: soc: ti: pruss: Add pruss_cfg_read()/update(), pruss_cfg_get_gpmux()/set_gpmux() APIs Add two new generic API pruss_cfg_read() and pruss_cfg_update() to the PRUSS platform driver to read and program respectively a register within the PRUSS CFG sub-module represented by a syscon driver. These APIs are internal to PRUSS driver. Add two new helper functions pruss_cfg_get_gpmux() & pruss_cfg_set_gpmux() to get and set the GP MUX mode for programming the PRUSS internal wrapper mux functionality as needed by usecases. Various useful registers and macros for certain register bit-fields and their values have also been added. Signed-off-by: Suman Anna Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Acked-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-4-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 45 ++++++++++++++++++++++ drivers/soc/ti/pruss.h | 88 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 32 ++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/soc/ti/pruss.h (limited to 'include') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index df5eb4d959f8..2c44913c083b 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -21,6 +21,7 @@ #include #include #include +#include "pruss.h" /** * struct pruss_private_data - PRUSS driver private data @@ -168,6 +169,50 @@ int pruss_release_mem_region(struct pruss *pruss, } EXPORT_SYMBOL_GPL(pruss_release_mem_region); +/** + * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: pointer to store the current mux value into + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux) +{ + int ret; + u32 val; + + if (pru_id >= PRUSS_NUM_PRUS || !mux) + return -EINVAL; + + ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val); + if (!ret) + *mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >> + PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); + return ret; +} +EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux); + +/** + * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: new mux value for PRU + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) +{ + if (mux >= PRUSS_GP_MUX_SEL_MAX || + pru_id >= PRUSS_NUM_PRUS) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_MUX_SEL_MASK, + (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h new file mode 100644 index 000000000000..6c55987e0e55 --- /dev/null +++ b/drivers/soc/ti/pruss.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * PRU-ICSS Subsystem user interfaces + * + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com + * MD Danish Anwar + */ + +#ifndef _SOC_TI_PRUSS_H_ +#define _SOC_TI_PRUSS_H_ + +#include +#include + +/* + * PRU_ICSS_CFG registers + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only + */ +#define PRUSS_CFG_REVID 0x00 +#define PRUSS_CFG_SYSCFG 0x04 +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) +#define PRUSS_CFG_CGR 0x10 +#define PRUSS_CFG_ISRP 0x14 +#define PRUSS_CFG_ISP 0x18 +#define PRUSS_CFG_IESP 0x1C +#define PRUSS_CFG_IECP 0x20 +#define PRUSS_CFG_SCRP 0x24 +#define PRUSS_CFG_PMAO 0x28 +#define PRUSS_CFG_MII_RT 0x2C +#define PRUSS_CFG_IEPCLK 0x30 +#define PRUSS_CFG_SPP 0x34 +#define PRUSS_CFG_PIN_MX 0x40 + +/* PRUSS_GPCFG register bits */ +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 + +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) + +/* PRUSS_MII_RT register bits */ +#define PRUSS_MII_RT_EVENT_EN BIT(0) + +/* PRUSS_SPP register bits */ +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) + +/** + * pruss_cfg_read() - read a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @val: pointer to return the value in + * + * Reads a given register within the PRUSS CFG sub-module and + * returns it through the passed-in @val pointer + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_read(pruss->cfg_regmap, reg, val); +} + +/** + * pruss_cfg_update() - configure a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @mask: bit mask to use for programming the @val + * @val: value to write + * + * Programs a given register within the PRUSS CFG sub-module + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_update(struct pruss *pruss, unsigned int reg, + unsigned int mask, unsigned int val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_update_bits(pruss->cfg_regmap, reg, mask, val); +} + +#endif /* _SOC_TI_PRUSS_H_ */ diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index c8f2e53b911b..5bb8897724a9 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -14,6 +14,24 @@ #include #include +/* + * enum pruss_gp_mux_sel - PRUSS GPI/O Mux modes for the + * PRUSS_GPCFG0/1 registers + * + * NOTE: The below defines are the most common values, but there + * are some exceptions like on 66AK2G, where the RESERVED and MII2 + * values are interchanged. Also, this bit-field does not exist on + * AM335x SoCs + */ +enum pruss_gp_mux_sel { + PRUSS_GP_MUX_SEL_GP, + PRUSS_GP_MUX_SEL_ENDAT, + PRUSS_GP_MUX_SEL_RESERVED, + PRUSS_GP_MUX_SEL_SD, + PRUSS_GP_MUX_SEL_MII2, + PRUSS_GP_MUX_SEL_MAX, +}; + /* * enum pruss_mem - PRUSS memory range identifiers */ @@ -66,6 +84,8 @@ int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, struct pruss_mem_region *region); int pruss_release_mem_region(struct pruss *pruss, struct pruss_mem_region *region); +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux); +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux); #else @@ -89,6 +109,18 @@ static inline int pruss_release_mem_region(struct pruss *pruss, return -EOPNOTSUPP; } +static inline int pruss_cfg_get_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 *mux) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int pruss_cfg_set_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 mux) +{ + return ERR_PTR(-EOPNOTSUPP); +} + #endif /* CONFIG_TI_PRUSS */ #endif /* _PRUSS_DRIVER_H_ */ -- cgit v1.2.3 From 0211cc1e4fbbc81853227147bf0982c47362c567 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 14 Apr 2023 10:25:42 +0530 Subject: soc: ti: pruss: Add helper functions to set GPI mode, MII_RT_event and XFR The PRUSS CFG module is represented as a syscon node and is currently managed by the PRUSS platform driver. Add easy accessor functions to set GPI mode, MII_RT event enable/disable and XFR (XIN XOUT) enable/disable to enable the PRUSS Ethernet usecase. These functions reuse the generic pruss_cfg_update() API function. Signed-off-by: Suman Anna Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Reviewed-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-5-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/remoteproc/pru_rproc.c | 15 --------- drivers/soc/ti/pruss.c | 71 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 51 ++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 095f66130f48..54f5ce302e7a 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -81,21 +81,6 @@ enum pru_iomem { PRU_IOMEM_MAX, }; -/** - * enum pru_type - PRU core type identifier - * - * @PRU_TYPE_PRU: Programmable Real-time Unit - * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit - * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit - * @PRU_TYPE_MAX: just keep this one at the end - */ -enum pru_type { - PRU_TYPE_PRU = 0, - PRU_TYPE_RTU, - PRU_TYPE_TX_PRU, - PRU_TYPE_MAX, -}; - /** * struct pru_private_data - device data for a PRU core * @type: type of the PRU core (PRU, RTU, Tx_PRU) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 2c44913c083b..7fdefee1ed87 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -213,6 +213,77 @@ int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) } EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); +/** + * pruss_cfg_gpimode() - set the GPI mode of the PRU + * @pruss: the pruss instance handle + * @pru_id: id of the PRU core within the PRUSS + * @mode: GPI mode to set + * + * Sets the GPI mode for a given PRU by programming the + * corresponding PRUSS_CFG_GPCFGx register + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode) +{ + if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_GPI_MODE_MASK, + mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_gpimode); + +/** + * pruss_cfg_miirt_enable() - Enable/disable MII RT Events + * @pruss: the pruss instance + * @enable: enable/disable + * + * Enable/disable the MII RT Events for the PRUSS. + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable) +{ + u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT, + PRUSS_MII_RT_EVENT_EN, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable); + +/** + * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality + * @pruss: the pruss instance + * @pru_type: PRU core type identifier + * @enable: enable/disable + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type, + bool enable) +{ + u32 mask, set; + + switch (pru_type) { + case PRU_TYPE_PRU: + mask = PRUSS_SPP_XFER_SHIFT_EN; + break; + case PRU_TYPE_RTU: + mask = PRUSS_SPP_RTU_XFR_SHIFT_EN; + break; + default: + return -EINVAL; + } + + set = enable ? mask : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index 5bb8897724a9..c9a31c567e85 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -32,6 +32,33 @@ enum pruss_gp_mux_sel { PRUSS_GP_MUX_SEL_MAX, }; +/* + * enum pruss_gpi_mode - PRUSS GPI configuration modes, used + * to program the PRUSS_GPCFG0/1 registers + */ +enum pruss_gpi_mode { + PRUSS_GPI_MODE_DIRECT, + PRUSS_GPI_MODE_PARALLEL, + PRUSS_GPI_MODE_28BIT_SHIFT, + PRUSS_GPI_MODE_MII, + PRUSS_GPI_MODE_MAX, +}; + +/** + * enum pru_type - PRU core type identifier + * + * @PRU_TYPE_PRU: Programmable Real-time Unit + * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit + * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit + * @PRU_TYPE_MAX: just keep this one at the end + */ +enum pru_type { + PRU_TYPE_PRU, + PRU_TYPE_RTU, + PRU_TYPE_TX_PRU, + PRU_TYPE_MAX, +}; + /* * enum pruss_mem - PRUSS memory range identifiers */ @@ -86,6 +113,11 @@ int pruss_release_mem_region(struct pruss *pruss, struct pruss_mem_region *region); int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux); int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux); +int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode); +int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable); +int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type, + bool enable); #else @@ -121,6 +153,25 @@ static inline int pruss_cfg_set_gpmux(struct pruss *pruss, return ERR_PTR(-EOPNOTSUPP); } +static inline int pruss_cfg_gpimode(struct pruss *pruss, + enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int pruss_cfg_xfr_enable(struct pruss *pruss, + enum pru_type pru_type, + bool enable); +{ + return ERR_PTR(-EOPNOTSUPP); +} + #endif /* CONFIG_TI_PRUSS */ #endif /* _PRUSS_DRIVER_H_ */ -- cgit v1.2.3 From e5b03cd101bd3dbbc7cbbe4c6e55a37070386494 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 29 Apr 2023 21:33:35 +0200 Subject: dt-bindings: arm: qcom,ids: Add IDs for IPQ5018 family Add SOC IDs for the IPQ5018 family. Signed-off-by: Robert Marko Acked-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230429193336.600629-1-robimarko@gmail.com --- include/dt-bindings/arm/qcom,ids.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 802495b20276..c1283bad81e1 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -216,6 +216,9 @@ #define QCOM_ID_SM8350 439 #define QCOM_ID_QCM2290 441 #define QCOM_ID_SM6115 444 +#define QCOM_ID_IPQ5010 446 +#define QCOM_ID_IPQ5018 447 +#define QCOM_ID_IPQ5028 448 #define QCOM_ID_SC8280XP 449 #define QCOM_ID_IPQ6005 453 #define QCOM_ID_QRB5165 455 @@ -229,6 +232,9 @@ #define QCOM_ID_SM8450_3 482 #define QCOM_ID_SC7280 487 #define QCOM_ID_SC7180P 495 +#define QCOM_ID_IPQ5000 503 +#define QCOM_ID_IPQ0509 504 +#define QCOM_ID_IPQ0518 505 #define QCOM_ID_SM6375 507 #define QCOM_ID_IPQ9514 510 #define QCOM_ID_IPQ9550 511 @@ -236,6 +242,7 @@ #define QCOM_ID_IPQ9570 513 #define QCOM_ID_IPQ9574 514 #define QCOM_ID_SM8550 519 +#define QCOM_ID_IPQ5016 520 #define QCOM_ID_IPQ9510 521 #define QCOM_ID_QRB4210 523 #define QCOM_ID_QRB2210 524 @@ -243,6 +250,7 @@ #define QCOM_ID_QRU1000 539 #define QCOM_ID_QDU1000 545 #define QCOM_ID_QDU1010 587 +#define QCOM_ID_IPQ5019 569 #define QCOM_ID_QRU1032 588 #define QCOM_ID_QRU1052 589 #define QCOM_ID_QRU1062 590 -- cgit v1.2.3 From fe78d73a914d86070ac15c9a6d1f885ce5bc4a69 Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Tue, 9 May 2023 09:05:30 +0530 Subject: dt-bindings: arm: qcom,ids: add SoC ID for IPQ5312 and IPQ5302 Add the SoC ID for IPQ5312 and IPQ5302, which belong to the family of IPQ5332 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan T Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230509033531.21468-2-quic_kathirav@quicinc.com --- include/dt-bindings/arm/qcom,ids.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index c1283bad81e1..69c2d8fa79f4 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -256,6 +256,8 @@ #define QCOM_ID_QRU1062 590 #define QCOM_ID_IPQ5332 592 #define QCOM_ID_IPQ5322 593 +#define QCOM_ID_IPQ5312 594 +#define QCOM_ID_IPQ5302 595 /* * The board type and revision information, used by Qualcomm bootloaders and -- cgit v1.2.3 From db967cf828fc134ba17c5e4539b1a3687cdd3f2d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 16 May 2023 22:12:12 +0200 Subject: arm-cci: add cci_enable_port_for_self prototype The cci_enable_port_for_self() is called from assembler, so add the prototype only to shut up the W=1 warning: drivers/bus/arm-cci.c:298:25: error: no previous prototype for 'cci_enable_port_for_self' [-Werror=missing-prototypes] Link: https://lore.kernel.org/r/20230516201218.556437-1-arnd@kernel.org Signed-off-by: Arnd Bergmann --- include/linux/arm-cci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h index d0e44201d855..7f7a576267bc 100644 --- a/include/linux/arm-cci.h +++ b/include/linux/arm-cci.h @@ -43,6 +43,8 @@ static inline int __cci_control_port_by_index(u32 port, bool enable) } #endif +void cci_enable_port_for_self(void); + #define cci_disable_port_by_device(dev) \ __cci_control_port_by_device(dev, false) #define cci_enable_port_by_device(dev) \ -- cgit v1.2.3 From ec001bb71e4476f7f5be9db693d5f43e65b9d8cb Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 26 May 2023 22:47:58 +0200 Subject: soc: qcom: socinfo: move SMEM item struct and defines to a header Move SMEM item struct and related defines to a header in order to be able to reuse them in the SMEM driver instead of duplicating them. Signed-off-by: Robert Marko Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526204802.3081168-1-robimarko@gmail.com --- drivers/soc/qcom/socinfo.c | 67 +------------------------------------- include/linux/soc/qcom/socinfo.h | 70 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 66 deletions(-) create mode 100644 include/linux/soc/qcom/socinfo.h (limited to 'include') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 0decf0a08468..dfd4330daef5 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,15 +33,6 @@ #define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) #define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) -#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 -#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 - -/* - * SMEM item id, used to acquire handles to respective - * SMEM region. - */ -#define SMEM_HW_SW_BUILD_ID 137 - #ifdef CONFIG_DEBUG_FS #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 #define SMEM_IMAGE_VERSION_SIZE 4096 @@ -126,64 +118,7 @@ static const char *const pmic_models[] = { [58] = "PM8450", [65] = "PM8010", }; -#endif /* CONFIG_DEBUG_FS */ - -/* Socinfo SMEM item structure */ -struct socinfo { - __le32 fmt; - __le32 id; - __le32 ver; - char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; - /* Version 2 */ - __le32 raw_id; - __le32 raw_ver; - /* Version 3 */ - __le32 hw_plat; - /* Version 4 */ - __le32 plat_ver; - /* Version 5 */ - __le32 accessory_chip; - /* Version 6 */ - __le32 hw_plat_subtype; - /* Version 7 */ - __le32 pmic_model; - __le32 pmic_die_rev; - /* Version 8 */ - __le32 pmic_model_1; - __le32 pmic_die_rev_1; - __le32 pmic_model_2; - __le32 pmic_die_rev_2; - /* Version 9 */ - __le32 foundry_id; - /* Version 10 */ - __le32 serial_num; - /* Version 11 */ - __le32 num_pmics; - __le32 pmic_array_offset; - /* Version 12 */ - __le32 chip_family; - __le32 raw_device_family; - __le32 raw_device_num; - /* Version 13 */ - __le32 nproduct_id; - char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; - /* Version 14 */ - __le32 num_clusters; - __le32 ncluster_array_offset; - __le32 num_defective_parts; - __le32 ndefective_parts_array_offset; - /* Version 15 */ - __le32 nmodem_supported; - /* Version 16 */ - __le32 feature_code; - __le32 pcode; - __le32 npartnamemap_offset; - __le32 nnum_partname_mapping; - /* Version 17 */ - __le32 oem_variant; -}; -#ifdef CONFIG_DEBUG_FS struct socinfo_params { u32 raw_device_family; u32 hw_plat_subtype; diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h new file mode 100644 index 000000000000..d1cbc49a2a2d --- /dev/null +++ b/include/linux/soc/qcom/socinfo.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __QCOM_SOCINFO_H__ +#define __QCOM_SOCINFO_H__ + +/* + * SMEM item id, used to acquire handles to respective + * SMEM region. + */ +#define SMEM_HW_SW_BUILD_ID 137 + +#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 +#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 + +/* Socinfo SMEM item structure */ +struct socinfo { + __le32 fmt; + __le32 id; + __le32 ver; + char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; + /* Version 2 */ + __le32 raw_id; + __le32 raw_ver; + /* Version 3 */ + __le32 hw_plat; + /* Version 4 */ + __le32 plat_ver; + /* Version 5 */ + __le32 accessory_chip; + /* Version 6 */ + __le32 hw_plat_subtype; + /* Version 7 */ + __le32 pmic_model; + __le32 pmic_die_rev; + /* Version 8 */ + __le32 pmic_model_1; + __le32 pmic_die_rev_1; + __le32 pmic_model_2; + __le32 pmic_die_rev_2; + /* Version 9 */ + __le32 foundry_id; + /* Version 10 */ + __le32 serial_num; + /* Version 11 */ + __le32 num_pmics; + __le32 pmic_array_offset; + /* Version 12 */ + __le32 chip_family; + __le32 raw_device_family; + __le32 raw_device_num; + /* Version 13 */ + __le32 nproduct_id; + char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; + /* Version 14 */ + __le32 num_clusters; + __le32 ncluster_array_offset; + __le32 num_defective_parts; + __le32 ndefective_parts_array_offset; + /* Version 15 */ + __le32 nmodem_supported; + /* Version 16 */ + __le32 feature_code; + __le32 pcode; + __le32 npartnamemap_offset; + __le32 nnum_partname_mapping; + /* Version 17 */ + __le32 oem_variant; +}; + +#endif -- cgit v1.2.3 From 17051d2c3cd696439adb900e9af547ba162fb982 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 26 May 2023 22:48:00 +0200 Subject: soc: qcom: smem: introduce qcom_smem_get_soc_id() Introduce a helper to return the SoC SMEM ID, which is used to identify the exact SoC model as there may be differences in the same SoC family. Currently, cpufreq-nvmem does this completely in the driver and there has been more interest expresed for other drivers to use this information so lets expose a common helper to prevent redoing it in individual drivers since this field is present on every SMEM table version. Signed-off-by: Robert Marko Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526204802.3081168-3-robimarko@gmail.com --- drivers/soc/qcom/smem.c | 23 +++++++++++++++++++++++ include/linux/soc/qcom/smem.h | 2 ++ 2 files changed, 25 insertions(+) (limited to 'include') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index bc98520c4969..b0d59e815c3b 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * The Qualcomm shared memory system is a allocate only heap structure that @@ -772,6 +773,28 @@ phys_addr_t qcom_smem_virt_to_phys(void *p) } EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); +/** + * qcom_smem_get_soc_id() - return the SoC ID + * @id: On success, we return the SoC ID here. + * + * Look up SoC ID from HW/SW build ID and return it. + * + * Return: 0 on success, negative errno on failure. + */ +int qcom_smem_get_soc_id(u32 *id) +{ + struct socinfo *info; + + info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); + if (IS_ERR(info)) + return PTR_ERR(info); + + *id = __le32_to_cpu(info->id); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); + static int qcom_smem_get_sbl_version(struct qcom_smem *smem) { struct smem_header *header; diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h index 86e1b358688a..223db6a9c733 100644 --- a/include/linux/soc/qcom/smem.h +++ b/include/linux/soc/qcom/smem.h @@ -11,4 +11,6 @@ int qcom_smem_get_free_space(unsigned host); phys_addr_t qcom_smem_virt_to_phys(void *p); +int qcom_smem_get_soc_id(u32 *id); + #endif -- cgit v1.2.3 From 59272ad8d9e8ea6398a96f8c6d62da284bf2ae6e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 10 Mar 2023 23:41:28 +0100 Subject: bus: fsl-mc: Make remove function return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value returned by an fsl-mc driver's remove function is mostly ignored. (Only an error message is printed if the value is non-zero and then device removal continues unconditionally.) So change the prototype of the remove function to return no value. This way driver authors are not tempted to assume that passing an error to the upper layer is a good idea. All drivers are adapted accordingly. There is no intended change of behaviour, all callbacks were prepared to return 0 before. Signed-off-by: Uwe Kleine-König Reviewed-by: Ioana Ciornei Tested-by: Ioana Ciornei # sanity checks Reviewed-by: Laurentiu Tudor Tested-by: Laurentiu Tudor Signed-off-by: Li Yang --- drivers/bus/fsl-mc/dprc-driver.c | 5 ++--- drivers/bus/fsl-mc/fsl-mc-allocator.c | 5 ++--- drivers/bus/fsl-mc/fsl-mc-bus.c | 5 +---- drivers/crypto/caam/caamalg_qi2.c | 4 +--- drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c | 4 +--- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 4 +--- drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c | 4 +--- drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 4 +--- drivers/soc/fsl/dpio/dpio-driver.c | 4 +--- drivers/vfio/fsl-mc/vfio_fsl_mc.c | 3 +-- include/linux/fsl/mc.h | 2 +- 11 files changed, 13 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c index ef4f43f67b80..595d4cecd041 100644 --- a/drivers/bus/fsl-mc/dprc-driver.c +++ b/drivers/bus/fsl-mc/dprc-driver.c @@ -835,13 +835,13 @@ EXPORT_SYMBOL_GPL(dprc_cleanup); * It tears down the interrupts that were configured for the DPRC device. * It destroys the interrupt pool associated with this MC bus. */ -static int dprc_remove(struct fsl_mc_device *mc_dev) +static void dprc_remove(struct fsl_mc_device *mc_dev) { struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); if (!mc_bus->irq_resources) { dev_err(&mc_dev->dev, "No irq resources, so unbinding the device failed\n"); - return 0; + return; } if (dev_get_msi_domain(&mc_dev->dev)) @@ -852,7 +852,6 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) dprc_cleanup(mc_dev); dev_info(&mc_dev->dev, "DPRC device unbound from driver"); - return 0; } static const struct fsl_mc_device_id match_id_table[] = { diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c index 36f70e5e418b..0ad68099684e 100644 --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c @@ -614,19 +614,18 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) * fsl_mc_allocator_remove - callback invoked when an allocatable device is * being removed from the system */ -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) +static void fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { int error; if (mc_dev->resource) { error = fsl_mc_resource_pool_remove_device(mc_dev); if (error < 0) - return 0; + return; } dev_dbg(&mc_dev->dev, "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); - return 0; } static const struct fsl_mc_device_id match_id_table[] = { diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 410693ff7335..4352745a923c 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -454,11 +454,8 @@ static int fsl_mc_driver_remove(struct device *dev) { struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - int error; - error = mc_drv->remove(mc_dev); - if (error < 0) - dev_err(dev, "%s failed: %d\n", __func__, error); + mc_drv->remove(mc_dev); return 0; } diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 5c8d35edaa1c..9156bbe038b7 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -5402,7 +5402,7 @@ err_dma_mask: return err; } -static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) +static void __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) { struct device *dev; struct dpaa2_caam_priv *priv; @@ -5443,8 +5443,6 @@ static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) free_percpu(priv->ppriv); fsl_mc_portal_free(priv->mc_io); kmem_cache_destroy(qi_cache); - - return 0; } int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req) diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c index 8dd40d00a672..a42a37634881 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c @@ -765,7 +765,7 @@ err_mcportal: return err; } -static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) +static void dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) { struct dpaa2_qdma_engine *dpaa2_qdma; struct dpaa2_qdma_priv *priv; @@ -787,8 +787,6 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) dma_async_device_unregister(&dpaa2_qdma->dma_dev); kfree(priv); kfree(dpaa2_qdma); - - return 0; } static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index a62cffaf6ff1..a9676d0dece8 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -5025,7 +5025,7 @@ err_wq_alloc: return err; } -static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) +static void dpaa2_eth_remove(struct fsl_mc_device *ls_dev) { struct device *dev; struct net_device *net_dev; @@ -5073,8 +5073,6 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); free_netdev(net_dev); - - return 0; } static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = { diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c index 90d23ab1ce9d..4497e3c0456d 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c @@ -219,7 +219,7 @@ err_exit: return err; } -static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) +static void dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) { struct device *dev = &mc_dev->dev; struct ptp_qoriq *ptp_qoriq; @@ -232,8 +232,6 @@ static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) fsl_mc_free_irqs(mc_dev); dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); fsl_mc_portal_free(mc_dev->mc_io); - - return 0; } static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = { diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index f4ae4289c41a..21cc4e52425a 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -3221,7 +3221,7 @@ static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev) dev_warn(dev, "dpsw_close err %d\n", err); } -static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) +static void dpaa2_switch_remove(struct fsl_mc_device *sw_dev) { struct ethsw_port_priv *port_priv; struct ethsw_core *ethsw; @@ -3252,8 +3252,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) kfree(ethsw); dev_set_drvdata(dev, NULL); - - return 0; } static int dpaa2_switch_probe_port(struct ethsw_core *ethsw, diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index 09df5302d255..9e3fddd8f5a9 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -270,7 +270,7 @@ static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) fsl_mc_free_irqs(dpio_dev); } -static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) +static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) { struct device *dev; struct dpio_priv *priv; @@ -299,8 +299,6 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) err_open: fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; } static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index c89a047a4cd8..f2140e94d41e 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -570,7 +570,7 @@ static void vfio_fsl_mc_release_dev(struct vfio_device *core_vdev) mutex_destroy(&vdev->igate); } -static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) +static void vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) { struct device *dev = &mc_dev->dev; struct vfio_fsl_mc_device *vdev = dev_get_drvdata(dev); @@ -578,7 +578,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) vfio_unregister_group_dev(&vdev->vdev); dprc_remove_devices(mc_dev, NULL, 0); vfio_put_device(&vdev->vdev); - return 0; } static const struct vfio_device_ops vfio_fsl_mc_ops = { diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index a86115bc799c..a1b3de87a3d1 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h @@ -48,7 +48,7 @@ struct fsl_mc_driver { struct device_driver driver; const struct fsl_mc_device_id *match_id_table; int (*probe)(struct fsl_mc_device *dev); - int (*remove)(struct fsl_mc_device *dev); + void (*remove)(struct fsl_mc_device *dev); void (*shutdown)(struct fsl_mc_device *dev); int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); int (*resume)(struct fsl_mc_device *dev); -- cgit v1.2.3 From 758cd5fc13b20a5874d33b7d381e78408743f587 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Wed, 31 May 2023 16:20:38 +0100 Subject: firmware: arm_scmi: Add Powercap protocol enable support SCMI powercap protocol v3.2 supports disabling the powercap on a zone by zone basis by providing a zero valued powercap. Expose new operations to enable/disable powercapping on a per-zone base. Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20230531152039.2363181-3-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/powercap.c | 110 +++++++++++++++++++++++++++++++++-- include/linux/scmi_protocol.h | 18 ++++++ 2 files changed, 122 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c index 2e490492f187..244929cb4f3e 100644 --- a/drivers/firmware/arm_scmi/powercap.c +++ b/drivers/firmware/arm_scmi/powercap.c @@ -108,6 +108,8 @@ struct scmi_powercap_meas_changed_notify_payld { }; struct scmi_powercap_state { + bool enabled; + u32 last_pcap; bool meas_notif_enabled; u64 thresholds; #define THRESH_LOW(p, id) \ @@ -412,6 +414,10 @@ static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, ignore_dresp); } + /* Save the last explicitly set non-zero powercap value */ + if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap) + pi->states[domain_id].last_pcap = power_cap; + return ret; } @@ -421,6 +427,20 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, { struct powercap_info *pi = ph->get_priv(ph); + /* + * Disallow zero as a possible explicitly requested powercap: + * there are enable/disable operations for this. + */ + if (!power_cap) + return -EINVAL; + + /* Just log the last set request if acting on a disabled domain */ + if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && + !pi->states[domain_id].enabled) { + pi->states[domain_id].last_pcap = power_cap; + return 0; + } + return __scmi_powercap_cap_set(ph, pi, domain_id, power_cap, ignore_dresp); } @@ -589,11 +609,78 @@ scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph, return ret; } +static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph, + u32 domain_id, bool enable) +{ + int ret; + u32 power_cap; + struct powercap_info *pi = ph->get_priv(ph); + + if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) + return -EINVAL; + + if (enable == pi->states[domain_id].enabled) + return 0; + + if (enable) { + /* Cannot enable with a zero powercap. */ + if (!pi->states[domain_id].last_pcap) + return -EINVAL; + + ret = __scmi_powercap_cap_set(ph, pi, domain_id, + pi->states[domain_id].last_pcap, + true); + } else { + ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true); + } + + if (ret) + return ret; + + /* + * Update our internal state to reflect final platform state: the SCMI + * server could have ignored a disable request and kept enforcing some + * powercap limit requested by other agents. + */ + ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); + if (!ret) + pi->states[domain_id].enabled = !!power_cap; + + return ret; +} + +static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph, + u32 domain_id, bool *enable) +{ + int ret; + u32 power_cap; + struct powercap_info *pi = ph->get_priv(ph); + + *enable = true; + if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) + return 0; + + /* + * Report always real platform state; platform could have ignored + * a previous disable request. Default true on any error. + */ + ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); + if (!ret) + *enable = !!power_cap; + + /* Update internal state with current real platform state */ + pi->states[domain_id].enabled = *enable; + + return 0; +} + static const struct scmi_powercap_proto_ops powercap_proto_ops = { .num_domains_get = scmi_powercap_num_domains_get, .info_get = scmi_powercap_dom_info_get, .cap_get = scmi_powercap_cap_get, .cap_set = scmi_powercap_cap_set, + .cap_enable_set = scmi_powercap_cap_enable_set, + .cap_enable_get = scmi_powercap_cap_enable_get, .pai_get = scmi_powercap_pai_get, .pai_set = scmi_powercap_pai_set, .measurements_get = scmi_powercap_measurements_get, @@ -854,6 +941,11 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph) if (!pinfo->powercaps) return -ENOMEM; + pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, + sizeof(*pinfo->states), GFP_KERNEL); + if (!pinfo->states) + return -ENOMEM; + /* * Note that any failure in retrieving any domain attribute leads to * the whole Powercap protocol initialization failure: this way the @@ -868,15 +960,21 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph) if (pinfo->powercaps[domain].fastchannels) scmi_powercap_domain_init_fc(ph, domain, &pinfo->powercaps[domain].fc_info); - } - pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, - sizeof(*pinfo->states), GFP_KERNEL); - if (!pinfo->states) - return -ENOMEM; + /* Grab initial state when disable is supported. */ + if (PROTOCOL_REV_MAJOR(version) >= 0x2) { + ret = __scmi_powercap_cap_get(ph, + &pinfo->powercaps[domain], + &pinfo->states[domain].last_pcap); + if (ret) + return ret; - pinfo->version = version; + pinfo->states[domain].enabled = + !!pinfo->states[domain].last_pcap; + } + } + pinfo->version = version; return ph->set_priv(ph, pinfo); } diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 0ce5746a4470..e6fe4f73ffe6 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -629,11 +629,25 @@ struct scmi_powercap_info { * @num_domains_get: get the count of powercap domains provided by SCMI. * @info_get: get the information for the specified domain. * @cap_get: get the current CAP value for the specified domain. + * On SCMI platforms supporting powercap zone disabling, this could + * report a zero value for a zone where powercapping is disabled. * @cap_set: set the CAP value for the specified domain to the provided value; * if the domain supports setting the CAP with an asynchronous command * this request will finally trigger an asynchronous transfer, but, if * @ignore_dresp here is set to true, this call will anyway return * immediately without waiting for the related delayed response. + * Note that the powercap requested value must NOT be zero, even if + * the platform supports disabling a powercap by setting its cap to + * zero (since SCMI v3.2): there are dedicated operations that should + * be used for that. (@cap_enable_set/get) + * @cap_enable_set: enable or disable the powercapping on the specified domain, + * if supported by the SCMI platform implementation. + * Note that, by the SCMI specification, the platform can + * silently ignore our disable request and decide to enforce + * anyway some other powercap value requested by another agent + * on the system: for this reason @cap_get and @cap_enable_get + * will always report the final platform view of the powercaps. + * @cap_enable_get: get the current CAP enable status for the specified domain. * @pai_get: get the current PAI value for the specified domain. * @pai_set: set the PAI value for the specified domain to the provided value. * @measurements_get: retrieve the current average power measurements for the @@ -662,6 +676,10 @@ struct scmi_powercap_proto_ops { u32 *power_cap); int (*cap_set)(const struct scmi_protocol_handle *ph, u32 domain_id, u32 power_cap, bool ignore_dresp); + int (*cap_enable_set)(const struct scmi_protocol_handle *ph, + u32 domain_id, bool enable); + int (*cap_enable_get)(const struct scmi_protocol_handle *ph, + u32 domain_id, bool *enable); int (*pai_get)(const struct scmi_protocol_handle *ph, u32 domain_id, u32 *pai); int (*pai_set)(const struct scmi_protocol_handle *ph, u32 domain_id, -- cgit v1.2.3 From 21d4631eedb136f101d2633b72cf42c20db79202 Mon Sep 17 00:00:00 2001 From: "Jason-JH.Lin" Date: Mon, 6 Mar 2023 16:06:59 +0800 Subject: soc: mediatek: remove DDP_DOMPONENT_DITHER from enum After mmsys and drm change DITHER enum to DDP_COMPONENT_DITHER0, mmsys header can remove the useless DDP_COMPONENT_DITHER enum. Signed-off-by: Jason-JH.Lin Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Rex-BC Chen Acked-by: Matthias Brugger Link: https://lore.kernel.org/r/20230306080659.15261-3-jason-jh.lin@mediatek.com Signed-off-by: Matthias Brugger --- include/linux/soc/mediatek/mtk-mmsys.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h index 37544ea6286d..2475ef914746 100644 --- a/include/linux/soc/mediatek/mtk-mmsys.h +++ b/include/linux/soc/mediatek/mtk-mmsys.h @@ -27,8 +27,7 @@ enum mtk_ddp_comp_id { DDP_COMPONENT_CCORR, DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR1, - DDP_COMPONENT_DITHER, - DDP_COMPONENT_DITHER0 = DDP_COMPONENT_DITHER, + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DITHER1, DDP_COMPONENT_DP_INTF0, DDP_COMPONENT_DP_INTF1, -- cgit v1.2.3 From 158826c73d48097f843bacc1bcafa6dbc114f4e5 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Tue, 6 Jun 2023 19:16:25 +0530 Subject: soc: qcom: socinfo: Add support for new fields in revision 18 Add support for below fields coming in socinfo structure under v18: * num_kvps: number of key value pairs (KVP) * kvps_offset: the offset of the KVP table from the base address of socinfo structure in SMEM KVP table has boolean values for certain feature flags, used to determine hardware configuration. Signed-off-by: Naman Jain Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230606134626.18790-2-quic_namajain@quicinc.com --- drivers/soc/qcom/socinfo.c | 1 + include/linux/soc/qcom/socinfo.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index dfd4330daef5..cb70f8439cfa 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -565,6 +565,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 18): case SOCINFO_VERSION(0, 17): qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root, diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h index d1cbc49a2a2d..3cc266d8a8b4 100644 --- a/include/linux/soc/qcom/socinfo.h +++ b/include/linux/soc/qcom/socinfo.h @@ -65,6 +65,9 @@ struct socinfo { __le32 nnum_partname_mapping; /* Version 17 */ __le32 oem_variant; + /* Version 18 */ + __le32 num_kvps; + __le32 kvps_offset; }; #endif -- cgit v1.2.3 From d9c2a255cfe026c8bf85a39631734f022ecefaff Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Tue, 6 Jun 2023 19:16:26 +0530 Subject: soc: qcom: socinfo: Add support for new fields in revision 19 Add support for below fields coming in socinfo structure under v19: * num_func_clusters: number of clusters with at least one functional core * boot_cluster: cluster selected as boot cluster * boot_core: core selected as boot core While at it, rename some variables to align them with their functionalities. Signed-off-by: Naman Jain Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230606134626.18790-3-quic_namajain@quicinc.com --- drivers/soc/qcom/socinfo.c | 32 ++++++++++++++++++++++++-------- include/linux/soc/qcom/socinfo.h | 8 ++++++-- 2 files changed, 30 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index cb70f8439cfa..a30d8bb6e938 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -133,12 +133,15 @@ struct socinfo_params { u32 nproduct_id; u32 num_clusters; u32 ncluster_array_offset; - u32 num_defective_parts; - u32 ndefective_parts_array_offset; + u32 num_subset_parts; + u32 nsubset_parts_array_offset; u32 nmodem_supported; u32 feature_code; u32 pcode; u32 oem_variant; + u32 num_func_clusters; + u32 boot_cluster; + u32 boot_core; }; struct smem_image_version { @@ -565,6 +568,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 19): + qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters); + qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster); + qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core); + + debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_func_clusters); + debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_cluster); + debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_core); + fallthrough; case SOCINFO_VERSION(0, 18): case SOCINFO_VERSION(0, 17): qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); @@ -589,17 +604,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, case SOCINFO_VERSION(0, 14): qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters); qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset); - 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); + qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts); + qcom_socinfo->info.nsubset_parts_array_offset = + __le32_to_cpu(info->nsubset_parts_array_offset); debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_clusters); debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_defective_parts); - debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.ndefective_parts_array_offset); + debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_subset_parts); + debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.nsubset_parts_array_offset); fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h index 3cc266d8a8b4..e78777bb0f4a 100644 --- a/include/linux/soc/qcom/socinfo.h +++ b/include/linux/soc/qcom/socinfo.h @@ -54,8 +54,8 @@ struct socinfo { /* Version 14 */ __le32 num_clusters; __le32 ncluster_array_offset; - __le32 num_defective_parts; - __le32 ndefective_parts_array_offset; + __le32 num_subset_parts; + __le32 nsubset_parts_array_offset; /* Version 15 */ __le32 nmodem_supported; /* Version 16 */ @@ -68,6 +68,10 @@ struct socinfo { /* Version 18 */ __le32 num_kvps; __le32 kvps_offset; + /* Version 19 */ + __le32 num_func_clusters; + __le32 boot_cluster; + __le32 boot_core; }; #endif -- cgit v1.2.3 From b56715957bc820ee4b01adfd6fa63fea63cd212a Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Mon, 5 Jun 2023 13:35:28 +0530 Subject: dt-bindings: arm: qcom,ids: add SoC ID for IPQ5300 Add the SoC ID for IPQ5300, which belong to the family of IPQ5332 SoC. Acked-by: Krzysztof Kozlowski Signed-off-by: Kathiravan T Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230605080531.3879-2-quic_kathirav@quicinc.com --- include/dt-bindings/arm/qcom,ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h index 69c2d8fa79f4..bcbe9ee2cdaf 100644 --- a/include/dt-bindings/arm/qcom,ids.h +++ b/include/dt-bindings/arm/qcom,ids.h @@ -258,6 +258,7 @@ #define QCOM_ID_IPQ5322 593 #define QCOM_ID_IPQ5312 594 #define QCOM_ID_IPQ5302 595 +#define QCOM_ID_IPQ5300 624 /* * The board type and revision information, used by Qualcomm bootloaders and -- cgit v1.2.3