All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shyam Kumar Thella <sthella@codeaurora.org>
To: srinivas.kandagatla@linaro.org
Cc: Shyam Kumar Thella <sthella@codeaurora.org>,
	agross@kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-msm@vger.kernel.org
Subject: [PATCH] nvmem: add QTI SDAM driver
Date: Tue, 17 Dec 2019 14:50:32 +0530	[thread overview]
Message-ID: <1576574432-9649-1-git-send-email-sthella@codeaurora.org> (raw)

QTI SDAM driver allows PMIC peripherals to access the shared memory
that is available on QTI PMICs.

Change-Id: I40005646ab1fbba9e0e4aa68e0a61cfbc7b51ba6
Signed-off-by: Shyam Kumar Thella <sthella@codeaurora.org>
---
 drivers/nvmem/Kconfig          |   8 ++
 drivers/nvmem/Makefile         |   1 +
 drivers/nvmem/qcom-spmi-sdam.c | 197 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+)
 create mode 100644 drivers/nvmem/qcom-spmi-sdam.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 73567e9..35efab1 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -109,6 +109,14 @@ config QCOM_QFPROM
 	  This driver can also be built as a module. If so, the module
 	  will be called nvmem_qfprom.
 
+config NVMEM_SPMI_SDAM
+	tristate "SPMI SDAM Support"
+	depends on SPMI
+	help
+	  This driver supports the Shared Direct Access Memory Module on
+	  Qualcomm Technologies, Inc. PMICs. It provides the clients
+	  an interface to read/write to the SDAM module's shared memory.
+
 config ROCKCHIP_EFUSE
 	tristate "Rockchip eFuse Support"
 	depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 9e66782..877a0b0 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_MTK_EFUSE)		+= nvmem_mtk-efuse.o
 nvmem_mtk-efuse-y		:= mtk-efuse.o
 obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
 nvmem_qfprom-y			:= qfprom.o
+obj-$(CONFIG_NVMEM_SPMI_SDAM)	+= qcom-spmi-sdam.o
 obj-$(CONFIG_ROCKCHIP_EFUSE)	+= nvmem_rockchip_efuse.o
 nvmem_rockchip_efuse-y		:= rockchip-efuse.o
 obj-$(CONFIG_ROCKCHIP_OTP)	+= nvmem-rockchip-otp.o
diff --git a/drivers/nvmem/qcom-spmi-sdam.c b/drivers/nvmem/qcom-spmi-sdam.c
new file mode 100644
index 0000000..e80a446
--- /dev/null
+++ b/drivers/nvmem/qcom-spmi-sdam.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
+
+#define SDAM_MEM_START			0x40
+#define REGISTER_MAP_ID			0x40
+#define REGISTER_MAP_VERSION		0x41
+#define SDAM_SIZE			0x44
+#define SDAM_PBS_TRIG_SET		0xE5
+#define SDAM_PBS_TRIG_CLR		0xE6
+
+struct sdam_chip {
+	struct platform_device		*pdev;
+	struct regmap			*regmap;
+	int				base;
+	int				size;
+};
+
+/* read only register offsets */
+static const u8 sdam_ro_map[] = {
+	REGISTER_MAP_ID,
+	REGISTER_MAP_VERSION,
+	SDAM_SIZE
+};
+
+static bool is_valid(struct sdam_chip *sdam, unsigned int offset, size_t len)
+{
+	int sdam_mem_end = SDAM_MEM_START + sdam->size - 1;
+
+	if (!len)
+		return false;
+
+	if (offset >= SDAM_MEM_START && offset <= sdam_mem_end
+				&& (offset + len - 1) <= sdam_mem_end)
+		return true;
+	else if ((offset == SDAM_PBS_TRIG_SET || offset == SDAM_PBS_TRIG_CLR)
+				&& (len == 1))
+		return true;
+
+	return false;
+}
+
+static bool is_ro(unsigned int offset, size_t len)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sdam_ro_map); i++)
+		if (offset <= sdam_ro_map[i] && (offset + len) > sdam_ro_map[i])
+			return true;
+
+	return false;
+}
+
+static int sdam_read(void *priv, unsigned int offset, void *val, size_t bytes)
+{
+	struct sdam_chip *sdam = priv;
+	int rc;
+
+	if (!is_valid(sdam, offset, bytes)) {
+		pr_err("Invalid SDAM offset 0x%02x len=%zd\n", offset, bytes);
+		return -EINVAL;
+	}
+
+	rc = regmap_bulk_read(sdam->regmap, sdam->base + offset, val, bytes);
+	if (rc < 0)
+		pr_err("Failed to read SDAM offset 0x%02x len=%zd, rc=%d\n",
+						offset, bytes, rc);
+
+	return rc;
+}
+
+static int sdam_write(void *priv, unsigned int offset, void *val, size_t bytes)
+{
+	struct sdam_chip *sdam = priv;
+	int rc;
+
+	if (!is_valid(sdam, offset, bytes)) {
+		pr_err("Invalid SDAM offset 0x%02x len=%zd\n", offset, bytes);
+		return -EINVAL;
+	}
+
+	if (is_ro(offset, bytes)) {
+		pr_err("Invalid write offset 0x%02x len=%zd\n", offset, bytes);
+		return -EINVAL;
+	}
+
+	rc = regmap_bulk_write(sdam->regmap, sdam->base + offset, val, bytes);
+	if (rc < 0)
+		pr_err("Failed to write SDAM offset 0x%02x len=%zd, rc=%d\n",
+						offset, bytes, rc);
+
+	return rc;
+}
+
+static int sdam_probe(struct platform_device *pdev)
+{
+	struct sdam_chip *sdam;
+	struct nvmem_device *nvmem;
+	struct nvmem_config *sdam_config;
+	unsigned int val = 0;
+	int rc;
+
+	sdam = devm_kzalloc(&pdev->dev, sizeof(*sdam), GFP_KERNEL);
+	if (!sdam)
+		return -ENOMEM;
+
+	sdam_config = devm_kzalloc(&pdev->dev, sizeof(*sdam_config),
+							GFP_KERNEL);
+	if (!sdam_config)
+		return -ENOMEM;
+
+	sdam->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!sdam->regmap) {
+		pr_err("Failed to get regmap handle\n");
+		return -ENXIO;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node, "reg", &sdam->base);
+	if (rc < 0) {
+		pr_err("Failed to get SDAM base, rc=%d\n", rc);
+		return -EINVAL;
+	}
+
+	rc = regmap_read(sdam->regmap, sdam->base + SDAM_SIZE, &val);
+	if (rc < 0) {
+		pr_err("Failed to read SDAM_SIZE rc=%d\n", rc);
+		return -EINVAL;
+	}
+	sdam->size = val * 32;
+
+	sdam_config->dev = &pdev->dev;
+	sdam_config->name = "spmi_sdam";
+	sdam_config->id = pdev->id;
+	sdam_config->owner = THIS_MODULE,
+	sdam_config->stride = 1;
+	sdam_config->word_size = 1;
+	sdam_config->reg_read = sdam_read;
+	sdam_config->reg_write = sdam_write;
+	sdam_config->priv = sdam;
+
+	nvmem = nvmem_register(sdam_config);
+	if (IS_ERR(nvmem)) {
+		pr_err("Failed to register SDAM nvmem device rc=%ld\n",
+						PTR_ERR(nvmem));
+		return -ENXIO;
+	}
+	platform_set_drvdata(pdev, nvmem);
+
+	pr_info("SDAM base=0x%04x size=%d registered successfully\n",
+						sdam->base, sdam->size);
+
+	return 0;
+}
+
+static int sdam_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sdam_match_table[] = {
+	{.compatible = "qcom,spmi-sdam"},
+	{},
+};
+
+static struct platform_driver sdam_driver = {
+	.driver = {
+		.name = "qcom,spmi-sdam",
+		.of_match_table = sdam_match_table,
+	},
+	.probe		= sdam_probe,
+	.remove		= sdam_remove,
+};
+
+static int __init sdam_init(void)
+{
+	return platform_driver_register(&sdam_driver);
+}
+subsys_initcall(sdam_init);
+
+static void __exit sdam_exit(void)
+{
+	return platform_driver_unregister(&sdam_driver);
+}
+module_exit(sdam_exit);
+
+MODULE_DESCRIPTION("QCOM SPMI SDAM driver");
+MODULE_LICENSE("GPL v2");
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
 a Linux Foundation Collaborative Project

             reply	other threads:[~2019-12-17  9:20 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-17  9:20 Shyam Kumar Thella [this message]
2019-12-18  6:14 ` [PATCH] nvmem: add QTI SDAM driver Bjorn Andersson
2019-12-19 10:29   ` sthella
2019-12-20  0:29     ` Bjorn Andersson
2019-12-23 10:51       ` sthella
2019-12-19 10:38 ` Srinivas Kandagatla

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1576574432-9649-1-git-send-email-sthella@codeaurora.org \
    --to=sthella@codeaurora.org \
    --cc=agross@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=srinivas.kandagatla@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.