lkml.org 
[lkml]   [2020]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 1/1] mfd: Add I2C based System Configuaration (SYSCON) access
Date
The existing SYSCON implementation only supports MMIO (memory mapped)
accesses, facilitated by Regmap. This extends support for registers
held behind I2C busses.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
Change log:

v1 => v2
- Remove legacy references to OF
- Allow building as a module (fixes h8300 0-day issue)

drivers/mfd/Kconfig | 7 +++
drivers/mfd/Makefile | 1 +
drivers/mfd/syscon-i2c.c | 90 ++++++++++++++++++++++++++++++++++
include/linux/mfd/syscon-i2c.h | 26 ++++++++++
4 files changed, 124 insertions(+)
create mode 100644 drivers/mfd/syscon-i2c.c
create mode 100644 include/linux/mfd/syscon-i2c.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0a59249198d34..f25f80f68edca 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1300,6 +1300,13 @@ config MFD_SYSCON
Select this option to enable accessing system control registers
via regmap.

+config MFD_SYSCON_I2C
+ tristate "System Controller Register R/W Based on I2C Regmap"
+ select REGMAP_I2C
+ help
+ Select this option to enable accessing system control registers
+ via I2C using regmap.
+
config MFD_DAVINCI_VOICECODEC
tristate
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f935d10cbf0fc..0aec1f42ac979 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -219,6 +219,7 @@ obj-$(CONFIG_MFD_RK808) += rk808.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
+obj-$(CONFIG_MFD_SYSCON_I2C) += syscon-i2c.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o
obj-$(CONFIG_MFD_RETU) += retu-mfd.o
diff --git a/drivers/mfd/syscon-i2c.c b/drivers/mfd/syscon-i2c.c
new file mode 100644
index 0000000000000..be20ff45ece07
--- /dev/null
+++ b/drivers/mfd/syscon-i2c.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * System Control Driver accessed over I2C
+ *
+ * Copyright (C) 2020 Linaro Ltd.
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/list.h>
+#include <linux/mfd/syscon-i2c.h>
+#include <linux/regmap.h>
+
+static DEFINE_SPINLOCK(syscon_i2c_list_slock);
+static LIST_HEAD(syscon_i2c_list);
+
+struct syscon {
+ struct device *dev;
+ struct regmap *regmap;
+ struct list_head list;
+};
+
+static const struct regmap_config syscon_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static struct syscon *syscon_i2c_register(struct i2c_client *client)
+{
+ struct regmap_config syscon_config = syscon_i2c_regmap_config;
+ struct device *dev = &client->dev;
+ struct syscon *syscon;
+ struct regmap *regmap;
+ int ret;
+
+ syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
+ if (!syscon)
+ return ERR_PTR(-ENOMEM);
+
+ syscon_config.name = dev_name(dev);
+
+ regmap = devm_regmap_init_i2c(client, &syscon_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to initialise Regmap I2C\n");
+ ret = PTR_ERR(regmap);
+ return ERR_PTR(ret);
+ }
+
+ syscon->regmap = regmap;
+ syscon->dev = dev;
+
+ spin_lock(&syscon_i2c_list_slock);
+ list_add_tail(&syscon->list, &syscon_i2c_list);
+ spin_unlock(&syscon_i2c_list_slock);
+
+ return syscon;
+}
+
+static struct regmap *syscon_i2c_get_regmap(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct syscon *entry, *syscon = NULL;
+
+ spin_lock(&syscon_i2c_list_slock);
+
+ list_for_each_entry(entry, &syscon_i2c_list, list)
+ if (entry->dev == dev) {
+ syscon = entry;
+ break;
+ }
+
+ spin_unlock(&syscon_i2c_list_slock);
+
+ if (!syscon)
+ syscon = syscon_i2c_register(client);
+
+ if (IS_ERR(syscon))
+ return ERR_CAST(syscon);
+
+ return syscon->regmap;
+}
+
+struct regmap *syscon_i2c_to_regmap(struct i2c_client *client)
+{
+ return syscon_i2c_get_regmap(client);
+}
+EXPORT_SYMBOL_GPL(syscon_i2c_to_regmap);
diff --git a/include/linux/mfd/syscon-i2c.h b/include/linux/mfd/syscon-i2c.h
new file mode 100644
index 0000000000000..e9ded6a363234
--- /dev/null
+++ b/include/linux/mfd/syscon-i2c.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * System Control Driver accessed via I2C
+ *
+ * Copyright (C) 2020 Linaro Ltd.
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ */
+
+#ifndef __LINUX_MFD_SYSCON_I2C_H__
+#define __LINUX_MFD_SYSCON_I2C_H__
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+
+#ifdef CONFIG_MFD_SYSCON_I2C
+extern struct regmap *syscon_i2c_to_regmap(struct i2c_client *client);
+#else
+static inline struct regmap *syscon_i2c_to_regmap(struct i2c_client *client)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+#endif
+
+#endif /* __LINUX_MFD_SYSCON_I2C_H__ */
--
2.25.1
\
 
 \ /
  Last update: 2020-06-17 10:43    [W:0.094 / U:0.048 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site