Implement nvmem-provider functionality in mtk-mfg-pmdomain, such that it can expose its GF_REG_SHADER_PRESENT value in the shared memory as an nvmem cell for panthor.
Signed-off-by: Nicolas Frattaroli <[email protected]> --- drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c b/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c index 9bad577b3ae4..3ce6fb74dd53 100644 --- a/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c +++ b/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c @@ -10,6 +10,7 @@ #include <linux/clk-provider.h> #include <linux/container_of.h> #include <linux/iopoll.h> +#include <linux/nvmem-provider.h> #include <linux/mailbox_client.h> #include <linux/module.h> #include <linux/of.h> @@ -872,6 +873,60 @@ static int mtk_mfg_init_clk_provider(struct mtk_mfg *mfg) return 0; } +static int mtk_mfg_read_nvmem(void *priv, unsigned int offset, void *val, size_t bytes) +{ + struct mtk_mfg *mfg = priv; + u32 *buf = val; + + if (bytes != 4) + return -EINVAL; + + if (!mfg->shared_mem) + return -ENODEV; + + if (offset + bytes >= mfg->shared_mem_size) + return -EINVAL; + + *buf = readl(mfg->shared_mem + offset); + + return 0; +} + +static int mtk_mfg_init_nvmem_provider(struct mtk_mfg *mfg) +{ + struct device *dev = &mfg->pdev->dev; + struct nvmem_cell_info cell = {}; + struct nvmem_config config = {}; + struct nvmem_device *nvdev; + int ret; + + config.reg_read = mtk_mfg_read_nvmem; + config.dev = dev; + config.read_only = true; + config.priv = mfg; + config.size = 4; + config.word_size = 4; + + nvdev = devm_nvmem_register(dev, &config); + if (IS_ERR(nvdev)) + return dev_err_probe(dev, PTR_ERR(nvdev), "Couldn't register nvmem provider\n"); + + cell.name = "shader-present"; + cell.offset = GF_REG_SHADER_PRESENT; + cell.bytes = 4; + cell.np = of_get_child_by_name(dev->of_node, cell.name); + + ret = nvmem_add_one_cell(nvdev, &cell); + if (ret) { + of_node_put(cell.np); + return dev_err_probe(dev, ret, "Couldn't add cell %s\n", cell.name); + } + + /* cell.np purposefully not put as nvmem_add_one_cell does not increase refcount */ + + return 0; +} + static int mtk_mfg_probe(struct platform_device *pdev) { struct mtk_mfg *mfg; @@ -984,6 +1039,10 @@ static int mtk_mfg_probe(struct platform_device *pdev) if (ret) goto err_power_off; + ret = mtk_mfg_init_nvmem_provider(mfg); + if (ret) + goto err_power_off; + ret = of_genpd_add_provider_simple(dev->of_node, &mfg->pd); if (ret) { dev_err_probe(dev, ret, "Failed to add pmdomain provider\n"); -- 2.52.0
