From patchwork Mon Jun 10 09:22:27 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas KANDAGATLA X-Patchwork-Id: 2697041 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 5F6C43FD4F for ; Mon, 10 Jun 2013 11:46:52 +0000 (UTC) Received: from merlin.infradead.org ([205.233.59.134]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlyMg-0006Pc-BN; Mon, 10 Jun 2013 09:26:17 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlyLc-0005Oe-EI; Mon, 10 Jun 2013 09:25:08 +0000 Received: from eu1sys200aog113.obsmtp.com ([207.126.144.135]) by merlin.infradead.org with smtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlyLZ-0005N9-KU for linux-arm-kernel@lists.infradead.org; Mon, 10 Jun 2013 09:25:06 +0000 Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob113.postini.com ([207.126.147.11]) with SMTP ID DSNKUbWbQule6sJ5XzMursVAkuyd3/Ejezvt@postini.com; Mon, 10 Jun 2013 09:25:05 UTC Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 1E784BB; Mon, 10 Jun 2013 09:24:15 +0000 (GMT) Received: from mail7.sgp.st.com (unknown [164.129.223.81]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0D62448C4; Mon, 10 Jun 2013 09:23:55 +0000 (GMT) Received: from localhost (king.bri.st.com [10.65.51.59]) by mail7.sgp.st.com (MOS 4.3.3-GA) with ESMTP id BFB57631 (AUTH srinivak); Mon, 10 Jun 2013 11:24:13 +0200 From: Srinivas KANDAGATLA To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support. Date: Mon, 10 Jun 2013 10:22:27 +0100 Message-Id: <1370856147-6552-1-git-send-email-srinivas.kandagatla@st.com> X-Mailer: git-send-email 1.7.6.5 In-Reply-To: <1370855828-5318-1-git-send-email-srinivas.kandagatla@st.com> References: <1370855828-5318-1-git-send-email-srinivas.kandagatla@st.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130610_052506_033911_590AF288 X-CRM114-Status: GOOD ( 28.42 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [207.126.144.135 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Mauro Carvalho Chehab , linux-doc@vger.kernel.org, Linus Walleij , linux@arm.linux.org.uk, Samuel Ortiz , Srinivas Kandagatla , Stephen Gallimore , linux-serial@vger.kernel.org, Grant Likely , Arnd Bergmann , devicetree-discuss@lists.ozlabs.org, Rob Herring , Stuart Menefy , Mark Brown , John Stultz , Thomas Gleixner , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Rob Landley , Olof Johansson , Andrew Morton , "David S. Miller" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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 CC: Stuart Menefy CC: Stephen Gallimore CC: Linus Walleij CC: Mark Brown --- .../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 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,-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 : 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 */