Message ID | 1370856147-6552-1-git-send-email-srinivas.kandagatla@st.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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 >
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
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 > >
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 --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 */
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