lkml.org 
[lkml]   [2022]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH 4/4] mfd: Samsung: Add Samsung sysmgr driver
From
Date
This driver is used for SoCs produced by Samsung Foundry to provide
Samsung sysmgr API. The read/write request of sysmgr is delivered to
Samsung secure monitor call.

Signed-off-by: Dongjin Yang <dj76.yang@samsung.com>
---
MAINTAINERS | 2 +
drivers/mfd/Kconfig | 11 +++
drivers/mfd/Makefile | 1 +
drivers/mfd/samsung-sysmgr.c | 167 +++++++++++++++++++++++++++++++++++++
include/linux/mfd/samsung-sysmgr.h | 30 +++++++
5 files changed, 211 insertions(+)
create mode 100644 drivers/mfd/samsung-sysmgr.c
create mode 100644 include/linux/mfd/samsung-sysmgr.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 55cb8901ccdc..44ad4bd406a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1870,9 +1870,11 @@ F: arch/arm/mach-artpec
F: drivers/clk/axis
F: drivers/crypto/axis
F: drivers/firmware/samsung-smc-svc.c
+F: drivers/mfd/samsung-sysmgr.c
F: drivers/mmc/host/usdhi6rol0.c
F: drivers/pinctrl/pinctrl-artpec*
F: include/linux/firmware/samsung-smc-svc.h
+F: include/linux/mfd/samsung-sysmgr.h

ARM/ASPEED I2C DRIVER
M: Brendan Higgins <brendanhiggins@google.com>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3b59456f5545..ce6ab5842bf0 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -51,6 +51,17 @@ config MFD_ACT8945A
linear regulators, along with a complete ActivePath battery
charger.

+config MFD_SAMSUNG_SYSMGR
+ bool "System Manager for Samsung Foundry platforms"
+ depends on ARCH_ARTPEC && OF
+ select MFD_SYSCON
+ select SAMSUNG_SECURE_SERVICE
+ help
+ Select this to get System Manager support for SoCs which use
+ Samsung Foundry platforms.
+ This System Manager has depedency on Samsung Secure Service
+ for providing secure service call.
+
config MFD_SUN4I_GPADC
tristate "Allwinner sunxi platforms' GPADC MFD driver"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 858cacf659d6..490f041d1262 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -248,6 +248,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o

obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
+obj-$(CONFIG_MFD_SAMSUNG_SYSMGR) += samsung-sysmgr.o
obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o

diff --git a/drivers/mfd/samsung-sysmgr.c b/drivers/mfd/samsung-sysmgr.c
new file mode 100644
index 000000000000..a202e8c4c4f2
--- /dev/null
+++ b/drivers/mfd/samsung-sysmgr.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Samsung Electronics, Co. Ltd.
+ * Copyright (C) 2018-2019, Intel Corporation.
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Inspired by drivers/mfd/altera-sysmgr.c
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/samsung-sysmgr.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/**
+ * struct samsung_sysmgr - Samsung System Manager
+ * @regmap: the regmap used for System Manager accesses.
+ * @base : the base address for the System Manager
+ */
+struct samsung_sysmgr {
+ struct regmap *regmap;
+ resource_size_t *base;
+};
+
+static struct platform_driver samsung_sysmgr_driver;
+
+static struct regmap_config mmio_regmap_cfg = {
+ .name = "sysmgr_mmio",
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static struct regmap_config samsung_smccc_regmap_cfg = {
+ .name = "samsung_sysmgr_smccc",
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+ .use_single_read = true,
+ .use_single_write = true,
+ .reg_read = samsung_smc_reg_read,
+ .reg_write = samsung_smc_reg_write,
+};
+
+/**
+ * samsung_sysmgr_regmap_lookup_by_phandle
+ * Find the sysmgr previous configured in probe() and return regmap property.
+ * Return: regmap if found or error if not found.
+ */
+struct regmap *samsung_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+ const char *property)
+{
+ struct device *dev;
+ struct samsung_sysmgr *sysmgr;
+ struct device_node *sysmgr_np;
+
+ if (property)
+ sysmgr_np = of_parse_phandle(np, property, 0);
+ else
+ sysmgr_np = np;
+
+ if (!sysmgr_np)
+ return ERR_PTR(-ENODEV);
+
+ dev = driver_find_device_by_of_node(&samsung_sysmgr_driver.driver,
+ (void *)sysmgr_np);
+ of_node_put(sysmgr_np);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ sysmgr = dev_get_drvdata(dev);
+
+ return sysmgr->regmap;
+}
+EXPORT_SYMBOL_GPL(samsung_sysmgr_regmap_lookup_by_phandle);
+
+static int sysmgr_probe(struct platform_device *pdev)
+{
+ struct samsung_sysmgr *sysmgr;
+ struct regmap *regmap;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct regmap_config sysmgr_config =
+ *((struct regmap_config *)of_device_get_match_data(dev));
+
+ sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL);
+ if (!sysmgr)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOENT;
+
+ sysmgr_config.max_register = resource_size(res) -
+ sysmgr_config.reg_stride;
+ if (sysmgr_config.reg_read) {
+ /* Need physical address for SMCC call */
+ sysmgr->base = (resource_size_t *)res->start;
+ regmap = devm_regmap_init(dev, NULL, sysmgr->base,
+ &sysmgr_config);
+ } else {
+ sysmgr->base = devm_ioremap(dev, res->start,
+ resource_size(res));
+ if (!sysmgr->base)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init_mmio(dev, sysmgr->base,
+ &sysmgr_config);
+ }
+
+ if (IS_ERR(regmap)) {
+ pr_err("regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+
+ sysmgr->regmap = regmap;
+
+ platform_set_drvdata(pdev, sysmgr);
+
+ return 0;
+}
+
+static const struct of_device_id samsung_sysmgr_of_match[] = {
+ { .compatible = "samsung,sys-mgr", .data = &mmio_regmap_cfg },
+ {
+ .compatible = "samsung,sys-mgr-smccc",
+ .data = &samsung_smccc_regmap_cfg
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, samsung_sysmgr_of_match);
+
+static struct platform_driver samsung_sysmgr_driver = {
+ .probe = sysmgr_probe,
+ .driver = {
+ .name = "samsung,system_manager",
+ .of_match_table = samsung_sysmgr_of_match,
+ },
+};
+
+static int __init samsung_sysmgr_init(void)
+{
+ return platform_driver_register(&samsung_sysmgr_driver);
+}
+core_initcall(samsung_sysmgr_init);
+
+static void __exit samsung_sysmgr_exit(void)
+{
+ platform_driver_unregister(&samsung_sysmgr_driver);
+}
+module_exit(samsung_sysmgr_exit);
+
+MODULE_AUTHOR("Dongjin Yang <dj76.yang@samsung.com>");
+MODULE_DESCRIPTION("Samsung System Manager driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/samsung-sysmgr.h b/include/linux/mfd/samsung-sysmgr.h
new file mode 100644
index 000000000000..d6887cb86ea8
--- /dev/null
+++ b/include/linux/mfd/samsung-sysmgr.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Samsung Electronics, Co. Ltd.
+ * Copyright (C) 2018-2019 Intel Corporation
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ */
+
+#ifndef __LINUX_MFD_SAMSUNG_SYSMGR_H__
+#define __LINUX_MFD_SAMSUNG_SYSMGR_H__
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/firmware/samsung-smc-svc.h>
+
+struct device_node;
+
+#if defined(CONFIG_MFD_SAMSUNG_SYSMGR)
+struct regmap *samsung_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+ const char *property);
+#else
+static inline struct regmap *
+samsung_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+ const char *property)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+#endif
+
+#endif /* __LINUX_MFD_SAMSUNG_SYSMGR_H__ */
--
2.9.5
\
 
 \ /
  Last update: 2022-07-13 06:59    [W:0.081 / U:2.300 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site