diff mbox

[v2,04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.

Message ID 1370856147-6552-1-git-send-email-srinivas.kandagatla@st.com (mailing list archive)
State New, archived
Headers show

Commit Message

Srinivas KANDAGATLA June 10, 2013, 9:22 a.m. UTC
System configuration(aka syscfg) registers are very basic configuration
registers arranged in groups across ST Settop Box parts.

The SOCs are assembled from existing IP blocks, which don't change very
often. However these blocks are assembled in different configurations to
meet the device requirements. So most IP blocks as well as having a bus
interface through which their own registers are accessible, will also
have a number of bristles(wires) which are signals that are going in and
out of the IP for configuration and status. To make these signals
accessible to software they are wired to "System Configuration
Registers".

Drivers target the IP blocks, which don't change much. Where as the
mapping of IP specific bristles(wires) to "System Configuration
Registers" do change per each SOC, and therefore we do not want this
information to be part of the driver.

Having a System Configuration infrastructure gives much flexibility and
abstraction to drivers to configure them. Typically in a SOC there will
be more than hundreds of these registers, which are again divided into
groups. The IP related config registers tend to much regular in latest
ST SOCs, so having a common place for configuring these registers makes
sense and avoid lot of code duplication.

This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.

This patch adds support to ST System Configuration registers, which can
be configured by the drivers.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Linus Walleij <linus.walleij@linaro.org>
CC: Mark Brown <broonie@kernel.org>
---
 .../devicetree/bindings/mfd/stixxxx-syscfg.txt     |   18 ++
 drivers/mfd/Kconfig                                |   10 ++
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/stixxxx-syscfg.c                       |  168 ++++++++++++++++++++
 include/linux/mfd/stixxxx-syscfg.h                 |   15 ++
 5 files changed, 212 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
 create mode 100644 drivers/mfd/stixxxx-syscfg.c
 create mode 100644 include/linux/mfd/stixxxx-syscfg.h

Comments

Linus Walleij June 10, 2013, 1:16 p.m. UTC | #1
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
<srinivas.kandagatla@st.com> wrote:

> This mfd driver provides higher level inialization routines for various
> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
> get to syscfg registers via standard regmap api which is usefull for
> drivers like pinctrl.
>
> This patch adds support to ST System Configuration registers, which can
> be configured by the drivers.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> CC: Stuart Menefy <stuart.menefy@st.com>
> CC: Stephen Gallimore <stephen.gallimore@st.com>
> CC: Linus Walleij <linus.walleij@linaro.org>
> CC: Mark Brown <broonie@kernel.org>

What is this driver doing that drivers/mfd/syscon.c is not already
doing?

I just get the feeling that you're reinventing the wheel here.

Yours,
Linus Walleij
Srinivas KANDAGATLA June 10, 2013, 1:52 p.m. UTC | #2
On 10/06/13 14:16, Linus Walleij wrote:
> On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
> <srinivas.kandagatla@st.com> wrote:
> 
>> This mfd driver provides higher level inialization routines for various
>> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
>> get to syscfg registers via standard regmap api which is usefull for
>> drivers like pinctrl.
>>
>> This patch adds support to ST System Configuration registers, which can
>> be configured by the drivers.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> CC: Stuart Menefy <stuart.menefy@st.com>
>> CC: Stephen Gallimore <stephen.gallimore@st.com>
>> CC: Linus Walleij <linus.walleij@linaro.org>
>> CC: Mark Brown <broonie@kernel.org>
> 
> What is this driver doing that drivers/mfd/syscon.c is not already
> doing?
As of now, the driver is very much similar to syscon + some additional
functionality, but we are planning to use this file to add higher level
functions to configure different IPs like ethernet, usb, power, reset
and so on which are very much specific to ST System Configuration Registers.

Thanks,
srini
> 
> I just get the feeling that you're reinventing the wheel here.
> 
> Yours,
> Linus Walleij
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>
Arnd Bergmann June 10, 2013, 2:02 p.m. UTC | #3
On Monday 10 June 2013 14:52:38 Srinivas KANDAGATLA wrote:
> On 10/06/13 14:16, Linus Walleij wrote:
> > On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
> > <srinivas.kandagatla@st.com> wrote:
> > 
> >> This mfd driver provides higher level inialization routines for various
> >> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
> >> get to syscfg registers via standard regmap api which is usefull for
> >> drivers like pinctrl.
> >>
> >> This patch adds support to ST System Configuration registers, which can
> >> be configured by the drivers.
> >>
> >> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> >> CC: Stuart Menefy <stuart.menefy@st.com>
> >> CC: Stephen Gallimore <stephen.gallimore@st.com>
> >> CC: Linus Walleij <linus.walleij@linaro.org>
> >> CC: Mark Brown <broonie@kernel.org>
> > 
> > What is this driver doing that drivers/mfd/syscon.c is not already
> > doing?
>
> As of now, the driver is very much similar to syscon + some additional
> functionality, but we are planning to use this file to add higher level
> functions to configure different IPs like ethernet, usb, power, reset
> and so on which are very much specific to ST System Configuration Registers.

I was expecting that you'd actually interface with the syscon code and
build on top, rather than copy it.

There are multiple ways of doing that, e.g. you could export a function
from syscon.c that you call to register the device node and then import
the regmap from syscon into your high-level driver again.

	Arnd
Srinivas KANDAGATLA June 10, 2013, 3:51 p.m. UTC | #4
Thanks for the comments.
On 10/06/13 15:02, Arnd Bergmann wrote:
> On Monday 10 June 2013 14:52:38 Srinivas KANDAGATLA wrote:
>> On 10/06/13 14:16, Linus Walleij wrote:
>>> On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
>>> <srinivas.kandagatla@st.com> wrote:
>>>
>>>> This mfd driver provides higher level inialization routines for various
>>>> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
>>>> get to syscfg registers via standard regmap api which is usefull for
>>>> drivers like pinctrl.
>>>>
>>>> This patch adds support to ST System Configuration registers, which can
>>>> be configured by the drivers.
>>>>
>>>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>>> CC: Stuart Menefy <stuart.menefy@st.com>
>>>> CC: Stephen Gallimore <stephen.gallimore@st.com>
>>>> CC: Linus Walleij <linus.walleij@linaro.org>
>>>> CC: Mark Brown <broonie@kernel.org>
>>>
>>> What is this driver doing that drivers/mfd/syscon.c is not already
>>> doing?
>>
>> As of now, the driver is very much similar to syscon + some additional
>> functionality, but we are planning to use this file to add higher level
>> functions to configure different IPs like ethernet, usb, power, reset
>> and so on which are very much specific to ST System Configuration Registers.
> 
> I was expecting that you'd actually interface with the syscon code and
> build on top, rather than copy it.
> 
I did not like the copying either, on the other hand I don't want to
pollute the syscon code.

As you said, I will make use of existing syscon and build "System
configuration interface" on top of it and see how it look like. It will
definitely get rid of lot of code duplication.

Thanks,
srini

> There are multiple ways of doing that, e.g. you could export a function
> from syscon.c that you call to register the device node and then import
> the regmap from syscon into your high-level driver again.

> 
> 	Arnd
> 
>
Srinivas KANDAGATLA June 11, 2013, 7:41 a.m. UTC | #5
On 10/06/13 15:02, Arnd Bergmann wrote:
> There are multiple ways of doing that, e.g. you could export a function
> from syscon.c that you call to register the device node and then import
> the regmap from syscon into your high-level driver again.
> 

Hi Arnd/Linus,

Thankyou for your comments,
I did try using the full sysconf names in compatible and make use of
syscon driver, with this change the nodes look much neater.

The nodes changes to:

syscfg_sbc:syscfg@fe600000{
    compatible      = "st,stih416-sbc-syscfg", "syscon";
    reg             = <0xfe600000 0x1000>;
};

From:
syscfg_sbc:syscfg@fe600000{
         compatible      = "st,stih416-syscfg";
         reg             = <0xfe600000 0x1000>;
         syscfg-range    = <0 999>;
         syscfg-name     = "SYSCFG_SBC";
};


Also I got rid of the drivers/mfd/stixxxx-syscfg.c driver all together
for this basic support patch series, I will add this once there are new
high level functions.
Additional compatible string will allow code to get to regmap via syscon
apis.

I will get rid of this driver in next version for this series.

Thanks,
srini

> 	Arnd
> 
>
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
new file mode 100644
index 0000000..428c751
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
@@ -0,0 +1,18 @@ 
+*STixxxx SYSCFG
+
+- compatible : should be "st,<SOC>-syscfg" like "st,stih415-syscfg"
+			or "st,stih416-syscfg".
+- reg, reg-names, interrupts, interrupt-names	: Standard way to define device
+			resources with names. look in
+			Documentation/devicetree/bindings/resource-names.txt
+- syscfg-range <start size> : Should be syscfg number range for this bank.
+- syscfg-name		    : Should be name of the syscfg, will be used in debugfs.
+
+Example of a SBC_SYSCFG bank node:
+
+syscfg_sbc: syscfg@fe600000{
+	compatible      = "st,stih415-syscfg";
+	reg		= <0xfe600000 0xb4>;
+	syscfg-range	= <0 44>;
+	syscfg-name	= "SYSCFG_SBC";
+};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d54e985..af49b58 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -649,6 +649,16 @@  config MFD_STA2X11
 	select MFD_CORE
 	select REGMAP_MMIO
 
+config MFD_STIXXXX_SYSCFG
+	bool "ST System Configuration Registers(aka syscfg) via regmap"
+	select REGMAP_MMIO
+	help
+	  Select this option to enable accessing STMicroelectronics
+	  System Configuration Registers via standard regmap apis with
+	  lookup helper functions.
+
+	  If unsure, say N.
+
 config MFD_SYSCON
 	bool "System Controller Register R/W Based on Regmap"
 	select REGMAP_MMIO
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 718e94a..c1f6570 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -150,6 +150,7 @@  obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
 obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
 obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_STIXXXX_SYSCFG)	+= stixxxx-syscfg.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
diff --git a/drivers/mfd/stixxxx-syscfg.c b/drivers/mfd/stixxxx-syscfg.c
new file mode 100644
index 0000000..10ea4e4
--- /dev/null
+++ b/drivers/mfd/stixxxx-syscfg.c
@@ -0,0 +1,168 @@ 
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Syscfg driver is used to configure various devices like Ethernet,
+ * USB, PCIE, SATA and so on.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/stixxxx-syscfg.h>
+
+#define DRIVER_NAME "stixxxx-syscfg"
+
+static struct platform_driver syscfg_driver;
+struct syscfg {
+	void __iomem *base;
+	struct regmap *regmap;
+	int	start, end;
+	const char *name;
+	struct device_node *of_node;
+};
+
+static int syscfg_match_name(struct device *dev, void *data)
+{
+	struct syscfg *syscfg = dev_get_drvdata(dev);
+
+	if (syscfg)
+		if (!strcmp(syscfg->name, (const char *)data))
+			return 1;
+	return 0;
+}
+
+struct regmap *syscfg_regmap_lookup_by_name(const char *name)
+{
+	struct syscfg *syscfg;
+	struct device *dev;
+
+	dev = driver_find_device(&syscfg_driver.driver, NULL, (void *)name,
+				 syscfg_match_name);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	syscfg = dev_get_drvdata(dev);
+
+	return syscfg->regmap;
+}
+
+static int syscfg_match_node(struct device *dev, void *data)
+{
+	struct device_node *dn = data;
+
+	return (dev->of_node == dn) ? 1 : 0;
+}
+
+struct regmap *syscfg_node_to_regmap(struct device_node *np)
+{
+	struct syscfg *syscfg;
+	struct device *dev;
+
+	dev = driver_find_device(&syscfg_driver.driver, NULL, np,
+				 syscfg_match_node);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	syscfg = dev_get_drvdata(dev);
+
+	return syscfg->regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_node_to_regmap);
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+					const char *property)
+{
+	struct device_node *syscfg_np;
+	struct regmap *regmap;
+
+	syscfg_np = of_parse_phandle(np, property, 0);
+	if (!syscfg_np)
+		return ERR_PTR(-ENODEV);
+
+	regmap = syscfg_node_to_regmap(syscfg_np);
+	of_node_put(syscfg_np);
+
+	return regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_regmap_lookup_by_phandle);
+
+static struct regmap_config syscfg_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int syscfg_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct syscfg *syscfg;
+	struct resource *res;
+	u32 range[2];
+
+	if (!np)
+		return -EINVAL;
+
+	syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
+	if (!syscfg)
+		return -ENOMEM;
+
+	syscfg->of_node = np;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	syscfg->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!syscfg->base) {
+		dev_err(&pdev->dev, "Unable to ioremap registers|\n");
+		return -ENODATA;
+	}
+
+	of_property_read_u32_array(np, "syscfg-range", (u32 *)&range, 2);
+	syscfg->start = range[0];
+	syscfg->end = range[0] + range[1];
+	of_property_read_string(np, "syscfg-name", &syscfg->name);
+
+	syscfg_regmap_config.name = kasprintf(GFP_KERNEL, "%s", syscfg->name);
+	syscfg_regmap_config.max_register = res->end - res->start - 3;
+	syscfg->regmap = devm_regmap_init_mmio(&pdev->dev, syscfg->base,
+					&syscfg_regmap_config);
+	if (IS_ERR(syscfg->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(syscfg->regmap);
+	}
+
+	platform_set_drvdata(pdev, syscfg);
+	dev_info(&pdev->dev,
+		"%s[%d - %d] sucessfully intialized\n",
+		syscfg->name, syscfg->start, syscfg->end);
+	return 0;
+}
+
+static struct of_device_id syscfg_match[] = {
+	{ .compatible = "st,stih415-syscfg", },
+	{ .compatible = "st,stih416-syscfg", },
+	{},
+};
+
+static struct platform_driver syscfg_driver = {
+	.probe		= syscfg_probe,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(syscfg_match),
+	},
+};
+
+static int __init syscfg_init(void)
+{
+	return platform_driver_register(&syscfg_driver);
+}
+postcore_initcall(syscfg_init);
diff --git a/include/linux/mfd/stixxxx-syscfg.h b/include/linux/mfd/stixxxx-syscfg.h
new file mode 100644
index 0000000..18ed6da7
--- /dev/null
+++ b/include/linux/mfd/stixxxx-syscfg.h
@@ -0,0 +1,15 @@ 
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+
+#ifndef __LINUX_MFD_STIXXXX_SYSCFG_H
+#define __LINUX_MFD_STIXXXX_SYSCFG_H
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+					const char *property);
+struct regmap *syscfg_regmap_lookup_by_name(const char *name);
+
+#endif /* __LINUX_MFD_STIXXXX_SYSCFG_H */