get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/810597/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 810597,
    "url": "http://patchwork.ozlabs.org/api/patches/810597/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/1504704043-8052-4-git-send-email-rf@opensource.wolfsonmicro.com/",
    "project": {
        "id": 42,
        "url": "http://patchwork.ozlabs.org/api/projects/42/?format=api",
        "name": "Linux GPIO development",
        "link_name": "linux-gpio",
        "list_id": "linux-gpio.vger.kernel.org",
        "list_email": "linux-gpio@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1504704043-8052-4-git-send-email-rf@opensource.wolfsonmicro.com>",
    "list_archive_url": null,
    "date": "2017-09-06T13:20:29",
    "name": "[v5,03/17] mfd: madera: Add common support for Cirrus Logic Madera codecs",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "a61e21100d593375b7737d1f966154bb31d8be6c",
    "submitter": {
        "id": 65141,
        "url": "http://patchwork.ozlabs.org/api/people/65141/?format=api",
        "name": "Richard Fitzgerald",
        "email": "rf@opensource.wolfsonmicro.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/1504704043-8052-4-git-send-email-rf@opensource.wolfsonmicro.com/mbox/",
    "series": [
        {
            "id": 1804,
            "url": "http://patchwork.ozlabs.org/api/series/1804/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=1804",
            "date": "2017-09-06T13:20:36",
            "name": "Add support for Cirrus Logic CS47L35/L85/L90/L91 codecs",
            "version": 5,
            "mbox": "http://patchwork.ozlabs.org/series/1804/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/810597/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/810597/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<linux-gpio-owner@vger.kernel.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-gpio-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ppops.net;\n\tspf=none smtp.mailfrom=rf@opensource.wolfsonmicro.com"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xnPTQ4hQlz9t2R\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed,  6 Sep 2017 23:25:14 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1754495AbdIFNZH (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tWed, 6 Sep 2017 09:25:07 -0400",
            "from mx0b-001ae601.pphosted.com ([67.231.152.168]:42786 \"EHLO\n\tmx0b-001ae601.pphosted.com\" rhost-flags-OK-OK-OK-OK)\n\tby vger.kernel.org with ESMTP id S1754571AbdIFNVE (ORCPT\n\t<rfc822; linux-gpio@vger.kernel.org>); Wed, 6 Sep 2017 09:21:04 -0400",
            "from pps.filterd (m0077474.ppops.net [127.0.0.1])\n\tby mx0b-001ae601.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id\n\tv86DJi86029115; Wed, 6 Sep 2017 08:20:45 -0500",
            "from mail4.cirrus.com ([87.246.98.35])\n\tby mx0b-001ae601.pphosted.com with ESMTP id 2cqs2mav5s-1;\n\tWed, 06 Sep 2017 08:20:45 -0500",
            "from EX17.ad.cirrus.com (unknown [172.20.9.81])\n\tby mail4.cirrus.com (Postfix) with ESMTP id 1EBFB611CE80;\n\tWed,  6 Sep 2017 08:20:44 -0500 (CDT)",
            "from imbe.wolfsonmicro.main (198.61.95.81) by EX17.ad.cirrus.com\n\t(172.20.9.81) with Microsoft SMTP Server id 14.3.301.0;\n\tWed, 6 Sep 2017 14:20:44 +0100",
            "from rf-debian.ad.cirrus.com (rf-debian.ad.cirrus.com\n\t[198.90.223.45]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP\n\tid v86DKhDN032150;        Wed, 6 Sep 2017 14:20:44 +0100"
        ],
        "From": "Richard Fitzgerald <rf@opensource.wolfsonmicro.com>",
        "To": "<lee.jones@linaro.org>, <broonie@kernel.org>,\n\t<linus.walleij@linaro.org>, <gnurou@gmail.com>,\n\t<robh+dt@kernel.org>, <tglx@linutronix.de>, <jason@lakedaemon.net>",
        "CC": "<alsa-devel@alsa-project.org>, <patches@opensource.wolfsonmicro.com>,\n\t<linux-gpio@vger.kernel.org>, <devicetree@vger.kernel.org>,\n\t<linux-kernel@vger.kernel.org>",
        "Subject": "[PATCH v5 03/17] mfd: madera: Add common support for Cirrus Logic\n\tMadera codecs",
        "Date": "Wed, 6 Sep 2017 14:20:29 +0100",
        "Message-ID": "<1504704043-8052-4-git-send-email-rf@opensource.wolfsonmicro.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1504704043-8052-1-git-send-email-rf@opensource.wolfsonmicro.com>",
        "References": "<1504704043-8052-1-git-send-email-rf@opensource.wolfsonmicro.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Proofpoint-Spam-Details": "rule=notspam policy=default score=0\n\tpriorityscore=1501 malwarescore=0\n\tsuspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011\n\tlowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam\n\tadjust=0\n\treason=mlx scancount=1 engine=8.0.1-1707230000\n\tdefinitions=main-1709060186",
        "Sender": "linux-gpio-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<linux-gpio.vger.kernel.org>",
        "X-Mailing-List": "linux-gpio@vger.kernel.org"
    },
    "content": "This adds the generic core support for Cirrus Logic \"Madera\" class codecs.\nThese are complex audio codec SoCs with a variety of digital and analogue\nI/O, onboard audio processing and DSPs, and other features.\n\nThese codecs are all based off a common set of hardware IP so can be\nsupported by a core of common code (with a few minor device-to-device\nvariations).\n\nSigned-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>\nSigned-off-by: Nikesh Oswal <Nikesh.Oswal@wolfsonmicro.com>\nSigned-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>\nAcked-for-MFD-by: Lee Jones <lee.jones@linaro.org>\n---\nChanges since V4:\n- Fixed Lee's review comments and applied ack as requested\n\n MAINTAINERS                      |   3 +\n drivers/mfd/Kconfig              |  27 ++\n drivers/mfd/Makefile             |   4 +\n drivers/mfd/madera-core.c        | 599 +++++++++++++++++++++++++++++++++++++++\n drivers/mfd/madera-i2c.c         | 139 +++++++++\n drivers/mfd/madera-spi.c         | 138 +++++++++\n drivers/mfd/madera.h             |  44 +++\n include/linux/mfd/madera/core.h  | 196 +++++++++++++\n include/linux/mfd/madera/pdata.h |  61 ++++\n 9 files changed, 1211 insertions(+)\n create mode 100644 drivers/mfd/madera-core.c\n create mode 100644 drivers/mfd/madera-i2c.c\n create mode 100644 drivers/mfd/madera-spi.c\n create mode 100644 drivers/mfd/madera.h\n create mode 100644 include/linux/mfd/madera/core.h\n create mode 100644 include/linux/mfd/madera/pdata.h",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex c03a393..642b9be 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -3425,7 +3425,10 @@ L:\tpatches@opensource.wolfsonmicro.com\n T:\tgit https://github.com/CirrusLogic/linux-drivers.git\n W:\thttps://github.com/CirrusLogic/linux-drivers/wiki\n S:\tSupported\n+F:\tDocumentation/devicetree/bindings/mfd/madera.txt\n F:\tinclude/linux/mfd/madera/*\n+F:\tdrivers/mfd/madera*\n+F:\tdrivers/mfd/cs47l*\n \n CLEANCACHE API\n M:\tKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>\ndiff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig\nindex fc5e4fe..cc14818 100644\n--- a/drivers/mfd/Kconfig\n+++ b/drivers/mfd/Kconfig\n@@ -222,6 +222,33 @@ config MFD_CROS_EC_SPI\n \t  response time cannot be guaranteed, we support ignoring\n \t  'pre-amble' bytes before the response actually starts.\n \n+config MFD_MADERA\n+\tbool\n+\tselect MFD_CORE\n+\tselect REGMAP\n+\tselect REGMAP_IRQ\n+\tselect MADERA_IRQ\n+\n+config MFD_MADERA_I2C\n+\tbool \"Cirrus Logic Madera codecs with I2C\"\n+\tselect MFD_MADERA\n+\tselect REGMAP_I2C\n+\tdepends on I2C\n+\tdepends on PINCTRL\n+\thelp\n+\t  Support for the Cirrus Logic Madera platform audio SoC\n+\t  core functionality controlled via I2C.\n+\n+config MFD_MADERA_SPI\n+\tbool \"Cirrus Logic Madera codecs with SPI\"\n+\tselect MFD_MADERA\n+\tselect REGMAP_SPI\n+\tdepends on SPI_MASTER\n+\tdepends on PINCTRL\n+\thelp\n+\t  Support for the Cirrus Logic Madera platform audio SoC\n+\t  core functionality controlled via SPI.\n+\n config MFD_ASIC3\n \tbool \"Compaq ASIC3\"\n \tdepends on GPIOLIB && ARM\ndiff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile\nindex c3d0a1b..1d03eef 100644\n--- a/drivers/mfd/Makefile\n+++ b/drivers/mfd/Makefile\n@@ -74,6 +74,10 @@ obj-$(CONFIG_MFD_WM8350_I2C)\t+= wm8350-i2c.o\n wm8994-objs\t\t\t:= wm8994-core.o wm8994-irq.o wm8994-regmap.o\n obj-$(CONFIG_MFD_WM8994)\t+= wm8994.o\n \n+obj-$(CONFIG_MFD_MADERA)\t+= madera-core.o\n+obj-$(CONFIG_MFD_MADERA_I2C)\t+= madera-i2c.o\n+obj-$(CONFIG_MFD_MADERA_SPI)\t+= madera-spi.o\n+\n obj-$(CONFIG_TPS6105X)\t\t+= tps6105x.o\n obj-$(CONFIG_TPS65010)\t\t+= tps65010.o\n obj-$(CONFIG_TPS6507X)\t\t+= tps6507x.o\ndiff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c\nnew file mode 100644\nindex 0000000..de1208b\n--- /dev/null\n+++ b/drivers/mfd/madera-core.c\n@@ -0,0 +1,599 @@\n+/*\n+ * Core MFD support for Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * Author: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#include <linux/device.h>\n+#include <linux/delay.h>\n+#include <linux/err.h>\n+#include <linux/gpio.h>\n+#include <linux/mfd/core.h>\n+#include <linux/module.h>\n+#include <linux/notifier.h>\n+#include <linux/of.h>\n+#include <linux/of_gpio.h>\n+#include <linux/platform_device.h>\n+#include <linux/pm_runtime.h>\n+#include <linux/regmap.h>\n+#include <linux/regulator/consumer.h>\n+#include <linux/regulator/machine.h>\n+#include <linux/regulator/of_regulator.h>\n+\n+#include <linux/mfd/madera/core.h>\n+#include <linux/mfd/madera/registers.h>\n+\n+#include \"madera.h\"\n+\n+#define CS47L35_SILICON_ID\t0x6360\n+#define CS47L85_SILICON_ID\t0x6338\n+#define CS47L90_SILICON_ID\t0x6364\n+\n+#define MADERA_32KZ_MCLK2\t1\n+\n+static const char * const madera_core_supplies[] = {\n+\t\"AVDD\",\n+\t\"DBVDD1\",\n+};\n+\n+static const struct mfd_cell madera_ldo1_devs[] = {\n+\t{ .name = \"madera-ldo1\" },\n+};\n+\n+static const char * const cs47l35_supplies[] = {\n+\t\"MICVDD\",\n+\t\"DBVDD2\",\n+\t\"CPVDD1\",\n+\t\"CPVDD2\",\n+\t\"SPKVDD\",\n+};\n+\n+static const struct mfd_cell cs47l35_devs[] = {\n+\t{ .name = \"madera-pinctrl\", },\n+\t{ .name = \"madera-irq\", },\n+\t{ .name = \"madera-micsupp\", },\n+\t{ .name = \"madera-gpio\", },\n+\t{ .name = \"madera-extcon\", },\n+\t{\n+\t\t.name = \"cs47l35-codec\",\n+\t\t.parent_supplies = cs47l35_supplies,\n+\t\t.num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),\n+\t},\n+};\n+\n+static const char * const cs47l85_supplies[] = {\n+\t\"MICVDD\",\n+\t\"DBVDD2\",\n+\t\"DBVDD3\",\n+\t\"DBVDD4\",\n+\t\"CPVDD1\",\n+\t\"CPVDD2\",\n+\t\"SPKVDDL\",\n+\t\"SPKVDDR\",\n+};\n+\n+static const struct mfd_cell cs47l85_devs[] = {\n+\t{ .name = \"madera-pinctrl\", },\n+\t{ .name = \"madera-irq\", },\n+\t{ .name = \"madera-micsupp\" },\n+\t{ .name = \"madera-gpio\", },\n+\t{ .name = \"madera-extcon\", },\n+\t{\n+\t\t.name = \"cs47l85-codec\",\n+\t\t.parent_supplies = cs47l85_supplies,\n+\t\t.num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),\n+\t},\n+};\n+\n+static const char * const cs47l90_supplies[] = {\n+\t\"MICVDD\",\n+\t\"DBVDD2\",\n+\t\"DBVDD3\",\n+\t\"DBVDD4\",\n+\t\"CPVDD1\",\n+\t\"CPVDD2\",\n+};\n+\n+static const struct mfd_cell cs47l90_devs[] = {\n+\t{ .name = \"madera-pinctrl\", },\n+\t{ .name = \"madera-irq\", },\n+\t{ .name = \"madera-micsupp\", },\n+\t{ .name = \"madera-gpio\", },\n+\t{ .name = \"madera-extcon\", },\n+\t{\n+\t\t.name = \"cs47l90-codec\",\n+\t\t.parent_supplies = cs47l90_supplies,\n+\t\t.num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),\n+\t},\n+};\n+\n+/* Used by madera-i2c and madera-spi drivers */\n+const char *madera_name_from_type(enum madera_type type)\n+{\n+\tswitch (type) {\n+\tcase CS47L35:\n+\t\treturn \"CS47L35\";\n+\tcase CS47L85:\n+\t\treturn \"CS47L85\";\n+\tcase CS47L90:\n+\t\treturn \"CS47L90\";\n+\tcase CS47L91:\n+\t\treturn \"CS47L91\";\n+\tcase WM1840:\n+\t\treturn \"WM1840\";\n+\tdefault:\n+\t\treturn \"Unknown\";\n+\t}\n+}\n+EXPORT_SYMBOL_GPL(madera_name_from_type);\n+\n+#define MADERA_BOOT_POLL_MAX_INTERVAL_US  5000\n+#define MADERA_BOOT_POLL_TIMEOUT_US\t 25000\n+\n+static int madera_wait_for_boot(struct madera *madera)\n+{\n+\tunsigned int val;\n+\tint ret;\n+\n+\t/*\n+\t * We can't use an interrupt as we need to runtime resume to do so,\n+\t * so we poll the status bit. This won't race with the interrupt\n+\t * handler because it will be blocked on runtime resume.\n+\t */\n+\tret = regmap_read_poll_timeout(madera->regmap,\n+\t\t\t\t       MADERA_IRQ1_RAW_STATUS_1,\n+\t\t\t\t       val,\n+\t\t\t\t       (val & MADERA_BOOT_DONE_STS1),\n+\t\t\t\t       MADERA_BOOT_POLL_MAX_INTERVAL_US,\n+\t\t\t\t       MADERA_BOOT_POLL_TIMEOUT_US);\n+\n+\tif (ret)\n+\t\tdev_err(madera->dev, \"Polling BOOT_DONE_STS failed: %d\\n\", ret);\n+\n+\t/*\n+\t * BOOT_DONE defaults to unmasked on boot so we must ack it.\n+\t * Do this unconditionally to avoid interrupt storms\n+\t */\n+\tregmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,\n+\t\t     MADERA_BOOT_DONE_EINT1);\n+\n+\tpm_runtime_mark_last_busy(madera->dev);\n+\n+\treturn ret;\n+}\n+\n+static int madera_soft_reset(struct madera *madera)\n+{\n+\tint ret;\n+\n+\tret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);\n+\tif (ret != 0) {\n+\t\tdev_err(madera->dev, \"Failed to soft reset device: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Allow time for internal clocks to startup after reset */\n+\tusleep_range(1000, 2000);\n+\n+\treturn 0;\n+}\n+\n+static void madera_enable_hard_reset(struct madera *madera)\n+{\n+\tif (madera->reset_gpio)\n+\t\tgpiod_set_value_cansleep(madera->reset_gpio, 0);\n+}\n+\n+static void madera_disable_hard_reset(struct madera *madera)\n+{\n+\tif (madera->reset_gpio) {\n+\t\tgpiod_set_value_cansleep(madera->reset_gpio, 1);\n+\t\tusleep_range(1000, 2000);\n+\t}\n+}\n+\n+#ifdef CONFIG_PM\n+static int madera_runtime_resume(struct device *dev)\n+{\n+\tstruct madera *madera = dev_get_drvdata(dev);\n+\tint ret;\n+\n+\tdev_dbg(dev, \"Leaving sleep mode\\n\");\n+\n+\tret = regulator_enable(madera->dcvdd);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to enable DCVDD: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tregcache_cache_only(madera->regmap, false);\n+\tregcache_cache_only(madera->regmap_32bit, false);\n+\n+\tret = madera_wait_for_boot(madera);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tret = regcache_sync(madera->regmap);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to restore 16-bit register cache\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tret = regcache_sync(madera->regmap_32bit);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to restore 32-bit register cache\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\tregcache_cache_only(madera->regmap_32bit, true);\n+\tregcache_cache_only(madera->regmap, true);\n+\tregulator_disable(madera->dcvdd);\n+\n+\treturn ret;\n+}\n+\n+static int madera_runtime_suspend(struct device *dev)\n+{\n+\tstruct madera *madera = dev_get_drvdata(dev);\n+\n+\tdev_dbg(madera->dev, \"Entering sleep mode\\n\");\n+\n+\tregcache_cache_only(madera->regmap, true);\n+\tregcache_mark_dirty(madera->regmap);\n+\tregcache_cache_only(madera->regmap_32bit, true);\n+\tregcache_mark_dirty(madera->regmap_32bit);\n+\n+\tregulator_disable(madera->dcvdd);\n+\n+\treturn 0;\n+}\n+#endif\n+\n+const struct dev_pm_ops madera_pm_ops = {\n+\tSET_RUNTIME_PM_OPS(madera_runtime_suspend,\n+\t\t\t   madera_runtime_resume,\n+\t\t\t   NULL)\n+};\n+EXPORT_SYMBOL_GPL(madera_pm_ops);\n+\n+const struct of_device_id madera_of_match[] = {\n+\t{ .compatible = \"cirrus,cs47l35\", .data = (void *)CS47L35 },\n+\t{ .compatible = \"cirrus,cs47l85\", .data = (void *)CS47L85 },\n+\t{ .compatible = \"cirrus,cs47l90\", .data = (void *)CS47L90 },\n+\t{ .compatible = \"cirrus,cs47l91\", .data = (void *)CS47L91 },\n+\t{ .compatible = \"cirrus,wm1840\", .data = (void *)WM1840 },\n+\t{},\n+};\n+EXPORT_SYMBOL_GPL(madera_of_match);\n+\n+static int madera_get_reset_gpio(struct madera *madera)\n+{\n+\tint ret = 0;\n+\n+\t/* We use 0 in pdata to indicate a GPIO has not been set */\n+\tif (dev_get_platdata(madera->dev) && (madera->pdata.reset > 0)) {\n+\t\t/* Start out with /RESET asserted */\n+\t\tret = devm_gpio_request_one(madera->dev,\n+\t\t\t\t\t    madera->pdata.reset,\n+\t\t\t\t\t    GPIOF_DIR_OUT | GPIOF_INIT_LOW,\n+\t\t\t\t\t    \"madera reset\");\n+\t\tif (!ret)\n+\t\t\tmadera->reset_gpio = gpio_to_desc(madera->pdata.reset);\n+\t} else {\n+\t\tmadera->reset_gpio = devm_gpiod_get_optional(madera->dev,\n+\t\t\t\t\t\t\t     \"reset\",\n+\t\t\t\t\t\t\t     GPIOD_OUT_LOW);\n+\t\tif (IS_ERR(madera->reset_gpio))\n+\t\t\tret = PTR_ERR(madera->reset_gpio);\n+\t}\n+\n+\tif (ret == -EPROBE_DEFER)\n+\t\treturn ret;\n+\n+\tif (ret) {\n+\t\tdev_err(madera->dev, \"Failed to request /RESET: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (!madera->reset_gpio)\n+\t\tdev_warn(madera->dev,\n+\t\t\t \"Running without reset GPIO is not recommended\\n\");\n+\n+\treturn 0;\n+}\n+\n+static void madera_set_micbias_info(struct madera *madera)\n+{\n+\t/*\n+\t * childbias is an array because future codecs can have different\n+\t * childbiases for each micbias\n+\t */\n+\tswitch (madera->type) {\n+\tcase CS47L35:\n+\t\tmadera->num_micbias = 2;\n+\t\tmadera->num_childbias[0] = 2;\n+\t\tmadera->num_childbias[1] = 2;\n+\t\treturn;\n+\tcase CS47L85:\n+\tcase WM1840:\n+\t\tmadera->num_micbias = 4;\n+\t\treturn;\n+\tcase CS47L90:\n+\tcase CS47L91:\n+\t\tmadera->num_micbias = 2;\n+\t\tmadera->num_childbias[0] = 4;\n+\t\tmadera->num_childbias[1] = 4;\n+\t\treturn;\n+\tdefault:\n+\t\treturn;\n+\t}\n+}\n+\n+int madera_dev_init(struct madera *madera)\n+{\n+\tstruct device *dev = madera->dev;\n+\tunsigned int hwid;\n+\tint (*patch_fn)(struct madera *) = NULL;\n+\tconst struct mfd_cell *mfd_devs;\n+\tint n_devs = 0;\n+\tint i, ret;\n+\n+\tdev_set_drvdata(madera->dev, madera);\n+\tBLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);\n+\tmadera_set_micbias_info(madera);\n+\n+\tif (dev_get_platdata(madera->dev)) {\n+\t\tmemcpy(&madera->pdata, dev_get_platdata(madera->dev),\n+\t\t       sizeof(madera->pdata));\n+\t}\n+\n+\tret = madera_get_reset_gpio(madera);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tregcache_cache_only(madera->regmap, true);\n+\tregcache_cache_only(madera->regmap_32bit, true);\n+\n+\tfor (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)\n+\t\tmadera->core_supplies[i].supply = madera_core_supplies[i];\n+\n+\tmadera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);\n+\n+\t/*\n+\t * On some codecs DCVDD could be supplied by the internal LDO1.\n+\t * For those we must add the LDO1 driver before requesting DCVDD\n+\t */\n+\tswitch (madera->type) {\n+\tcase CS47L35:\n+\tcase CS47L90:\n+\tcase CS47L91:\n+\t\tbreak;\n+\tcase CS47L85:\n+\tcase WM1840:\n+\t\tret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,\n+\t\t\t\t      madera_ldo1_devs,\n+\t\t\t\t      ARRAY_SIZE(madera_ldo1_devs),\n+\t\t\t\t      NULL, 0, NULL);\n+\t\tif (ret) {\n+\t\t\tdev_err(dev, \"Failed to add LDO1 child: %d\\n\", ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\t/* No point continuing if the type is unknown */\n+\t\tdev_err(madera->dev, \"Unknown device type %d\\n\", madera->type);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tret = devm_regulator_bulk_get(dev, madera->num_core_supplies,\n+\t\t\t\t      madera->core_supplies);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to request core supplies: %d\\n\", ret);\n+\t\tgoto err_devs;\n+\t}\n+\n+\t/*\n+\t * Don't use devres here because the only device we have to get\n+\t * against is the MFD device and DCVDD will likely be supplied by\n+\t * one of its children. Meaning that the regulator will be\n+\t * destroyed by the time devres calls regulator put.\n+\t */\n+\tmadera->dcvdd = regulator_get_exclusive(madera->dev, \"DCVDD\");\n+\tif (IS_ERR(madera->dcvdd)) {\n+\t\tret = PTR_ERR(madera->dcvdd);\n+\t\tdev_err(dev, \"Failed to request DCVDD: %d\\n\", ret);\n+\t\tgoto err_devs;\n+\t}\n+\n+\tret = regulator_bulk_enable(madera->num_core_supplies,\n+\t\t\t\t    madera->core_supplies);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to enable core supplies: %d\\n\", ret);\n+\t\tgoto err_dcvdd;\n+\t}\n+\n+\tret = regulator_enable(madera->dcvdd);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to enable DCVDD: %d\\n\", ret);\n+\t\tgoto err_enable;\n+\t}\n+\n+\tmadera_disable_hard_reset(madera);\n+\n+\tregcache_cache_only(madera->regmap, false);\n+\tregcache_cache_only(madera->regmap_32bit, false);\n+\n+\t/*\n+\t * Verify that this is a chip we know about before we\n+\t * starting doing any writes to its registers\n+\t */\n+\tret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to read ID register: %d\\n\", ret);\n+\t\tgoto err_reset;\n+\t}\n+\n+\tswitch (hwid) {\n+\tcase CS47L35_SILICON_ID:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L35)) {\n+\t\t\tswitch (madera->type) {\n+\t\t\tcase CS47L35:\n+\t\t\t\tpatch_fn = cs47l35_patch;\n+\t\t\t\tmfd_devs = cs47l35_devs;\n+\t\t\t\tn_devs = ARRAY_SIZE(cs47l35_devs);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L85_SILICON_ID:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L85)) {\n+\t\t\tswitch (madera->type) {\n+\t\t\tcase CS47L85:\n+\t\t\tcase WM1840:\n+\t\t\t\tpatch_fn = cs47l85_patch;\n+\t\t\t\tmfd_devs = cs47l85_devs;\n+\t\t\t\tn_devs = ARRAY_SIZE(cs47l85_devs);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L90_SILICON_ID:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L90)) {\n+\t\t\tswitch (madera->type) {\n+\t\t\tcase CS47L90:\n+\t\t\tcase CS47L91:\n+\t\t\t\tpatch_fn = cs47l90_patch;\n+\t\t\t\tmfd_devs = cs47l90_devs;\n+\t\t\t\tn_devs = ARRAY_SIZE(cs47l90_devs);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(madera->dev, \"Unknown device ID: %x\\n\", hwid);\n+\t\tret = -EINVAL;\n+\t\tgoto err_reset;\n+\t}\n+\n+\tif (!n_devs) {\n+\t\tdev_err(madera->dev, \"Device ID 0x%x not a %s\\n\", hwid,\n+\t\t\tmadera->type_name);\n+\t\tret = -ENODEV;\n+\t\tgoto err_reset;\n+\t}\n+\n+\t/*\n+\t * It looks like a device we support. If we don't have a hard reset\n+\t * we can now attempt a soft reset\n+\t */\n+\tif (!madera->reset_gpio) {\n+\t\tret = madera_soft_reset(madera);\n+\t\tif (ret)\n+\t\t\tgoto err_reset;\n+\t}\n+\n+\tret = madera_wait_for_boot(madera);\n+\tif (ret) {\n+\t\tdev_err(madera->dev, \"Device failed initial boot: %d\\n\", ret);\n+\t\tgoto err_reset;\n+\t}\n+\n+\tret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,\n+\t\t\t  &madera->rev);\n+\tif (ret) {\n+\t\tdev_err(dev, \"Failed to read revision register: %d\\n\", ret);\n+\t\tgoto err_reset;\n+\t}\n+\tmadera->rev &= MADERA_HW_REVISION_MASK;\n+\n+\tdev_info(dev, \"%s silicon revision %d\\n\", madera->type_name,\n+\t\t madera->rev);\n+\n+\t/* Apply hardware patch */\n+\tif (patch_fn) {\n+\t\tret = patch_fn(madera);\n+\t\tif (ret) {\n+\t\t\tdev_err(madera->dev, \"Failed to apply patch %d\\n\", ret);\n+\t\t\tgoto err_reset;\n+\t\t}\n+\t}\n+\n+\t/* Init 32k clock sourced from MCLK2 */\n+\tret = regmap_update_bits(madera->regmap,\n+\t\t\tMADERA_CLOCK_32K_1,\n+\t\t\tMADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,\n+\t\t\tMADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);\n+\tif (ret) {\n+\t\tdev_err(madera->dev, \"Failed to init 32k clock: %d\\n\", ret);\n+\t\tgoto err_reset;\n+\t}\n+\n+\tpm_runtime_set_active(madera->dev);\n+\tpm_runtime_enable(madera->dev);\n+\tpm_runtime_set_autosuspend_delay(madera->dev, 100);\n+\tpm_runtime_use_autosuspend(madera->dev);\n+\n+\tret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,\n+\t\t\t      mfd_devs, n_devs,\n+\t\t\t      NULL, 0, NULL);\n+\tif (ret) {\n+\t\tdev_err(madera->dev, \"Failed to add subdevices: %d\\n\", ret);\n+\t\tgoto err_pm_runtime;\n+\t}\n+\n+\treturn 0;\n+\n+err_pm_runtime:\n+\tpm_runtime_disable(madera->dev);\n+err_reset:\n+\tmadera_enable_hard_reset(madera);\n+\tregulator_disable(madera->dcvdd);\n+err_enable:\n+\tregulator_bulk_disable(madera->num_core_supplies,\n+\t\t\t       madera->core_supplies);\n+err_dcvdd:\n+\tregulator_put(madera->dcvdd);\n+err_devs:\n+\tmfd_remove_devices(dev);\n+\n+\treturn ret;\n+}\n+EXPORT_SYMBOL_GPL(madera_dev_init);\n+\n+int madera_dev_exit(struct madera *madera)\n+{\n+\t/* Prevent any IRQs being serviced while we clean up */\n+\tdisable_irq(madera->irq);\n+\n+\t/*\n+\t * DCVDD could be supplied by a child node, we must disable it before\n+\t * removing the children, and prevent PM runtime from turning it back on\n+\t */\n+\tpm_runtime_disable(madera->dev);\n+\n+\tregulator_disable(madera->dcvdd);\n+\tregulator_put(madera->dcvdd);\n+\n+\tmfd_remove_devices(madera->dev);\n+\tmadera_enable_hard_reset(madera);\n+\n+\tregulator_bulk_disable(madera->num_core_supplies,\n+\t\t\t       madera->core_supplies);\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(madera_dev_exit);\ndiff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c\nnew file mode 100644\nindex 0000000..526ab7c\n--- /dev/null\n+++ b/drivers/mfd/madera-i2c.c\n@@ -0,0 +1,139 @@\n+/*\n+ * I2C bus interface to Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#include <linux/device.h>\n+#include <linux/err.h>\n+#include <linux/i2c.h>\n+#include <linux/module.h>\n+#include <linux/of.h>\n+#include <linux/of_device.h>\n+#include <linux/regmap.h>\n+\n+#include <linux/mfd/madera/core.h>\n+\n+#include \"madera.h\"\n+\n+static int madera_i2c_probe(struct i2c_client *i2c,\n+\t\t\t    const struct i2c_device_id *id)\n+{\n+\tstruct madera *madera;\n+\tconst struct regmap_config *regmap_16bit_config = NULL;\n+\tconst struct regmap_config *regmap_32bit_config = NULL;\n+\tconst struct of_device_id *of_id;\n+\tunsigned long type = 0;\n+\tconst char *name;\n+\tint ret;\n+\n+\tif (i2c->dev.of_node)\n+\t\tof_id = of_match_device(madera_of_match, &i2c->dev);\n+\t\tif (of_id)\n+\t\t\ttype = (unsigned long)of_id->data;\n+\telse\n+\t\ttype = id->driver_data;\n+\n+\tswitch (type) {\n+\tcase CS47L35:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L35)) {\n+\t\t\tregmap_16bit_config = &cs47l35_16bit_i2c_regmap;\n+\t\t\tregmap_32bit_config = &cs47l35_32bit_i2c_regmap;\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L85:\n+\tcase WM1840:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L85)) {\n+\t\t\tregmap_16bit_config = &cs47l85_16bit_i2c_regmap;\n+\t\t\tregmap_32bit_config = &cs47l85_32bit_i2c_regmap;\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L90:\n+\tcase CS47L91:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L90)) {\n+\t\t\tregmap_16bit_config = &cs47l90_16bit_i2c_regmap;\n+\t\t\tregmap_32bit_config = &cs47l90_32bit_i2c_regmap;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(&i2c->dev,\n+\t\t\t\"Unknown Madera I2C device type %ld\\n\", type);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tname = madera_name_from_type(type);\n+\n+\tif (!regmap_16bit_config) {\n+\t\tdev_err(&i2c->dev,\n+\t\t\t\"Kernel does not include support for %s\\n\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmadera = devm_kzalloc(&i2c->dev, sizeof(*madera), GFP_KERNEL);\n+\tif (!madera)\n+\t\treturn -ENOMEM;\n+\n+\n+\tmadera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);\n+\tif (IS_ERR(madera->regmap)) {\n+\t\tret = PTR_ERR(madera->regmap);\n+\t\tdev_err(&i2c->dev,\n+\t\t\t\"Failed to allocate 16-bit register map: %d\\n\",\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tmadera->regmap_32bit = devm_regmap_init_i2c(i2c, regmap_32bit_config);\n+\tif (IS_ERR(madera->regmap_32bit)) {\n+\t\tret = PTR_ERR(madera->regmap_32bit);\n+\t\tdev_err(&i2c->dev,\n+\t\t\t\"Failed to allocate 32-bit register map: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tmadera->type = type;\n+\tmadera->type_name = name;\n+\tmadera->dev = &i2c->dev;\n+\tmadera->irq = i2c->irq;\n+\n+\treturn madera_dev_init(madera);\n+}\n+\n+static int madera_i2c_remove(struct i2c_client *i2c)\n+{\n+\tstruct madera *madera = dev_get_drvdata(&i2c->dev);\n+\n+\tmadera_dev_exit(madera);\n+\n+\treturn 0;\n+}\n+\n+static const struct i2c_device_id madera_i2c_id[] = {\n+\t{ \"cs47l35\", CS47L35 },\n+\t{ \"cs47l85\", CS47L85 },\n+\t{ \"cs47l90\", CS47L90 },\n+\t{ \"cs47l91\", CS47L91 },\n+\t{ \"wm1840\", WM1840 },\n+\t{ }\n+};\n+MODULE_DEVICE_TABLE(i2c, madera_i2c_id);\n+\n+static struct i2c_driver madera_i2c_driver = {\n+\t.driver = {\n+\t\t.name\t= \"madera\",\n+\t\t.pm\t= &madera_pm_ops,\n+\t\t.of_match_table\t= of_match_ptr(madera_of_match),\n+\t},\n+\t.probe\t\t= madera_i2c_probe,\n+\t.remove\t\t= madera_i2c_remove,\n+\t.id_table\t= madera_i2c_id,\n+};\n+\n+module_i2c_driver(madera_i2c_driver);\n+\n+MODULE_DESCRIPTION(\"Madera I2C bus interface\");\n+MODULE_AUTHOR(\"Richard Fitzgerald <rf@opensource.wolfsonmicro.com>\");\n+MODULE_LICENSE(\"GPL v2\");\ndiff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c\nnew file mode 100644\nindex 0000000..5280c42\n--- /dev/null\n+++ b/drivers/mfd/madera-spi.c\n@@ -0,0 +1,138 @@\n+/*\n+ * SPI bus interface to Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#include <linux/device.h>\n+#include <linux/err.h>\n+#include <linux/module.h>\n+#include <linux/of.h>\n+#include <linux/of_device.h>\n+#include <linux/regmap.h>\n+#include <linux/spi/spi.h>\n+\n+#include <linux/mfd/madera/core.h>\n+\n+#include \"madera.h\"\n+\n+static int madera_spi_probe(struct spi_device *spi)\n+{\n+\tconst struct spi_device_id *id = spi_get_device_id(spi);\n+\tstruct madera *madera;\n+\tconst struct regmap_config *regmap_16bit_config = NULL;\n+\tconst struct regmap_config *regmap_32bit_config = NULL;\n+\tconst struct of_device_id *of_id;\n+\tunsigned long type = 0;\n+\tconst char *name;\n+\tint ret;\n+\n+\tif (spi->dev.of_node)\n+\t\tof_id = of_match_device(madera_of_match, &spi->dev);\n+\t\tif (of_id)\n+\t\t\ttype = (unsigned long)of_id->data;\n+\telse\n+\t\ttype = id->driver_data;\n+\n+\tswitch (type) {\n+\tcase CS47L35:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L35)) {\n+\t\t\tregmap_16bit_config = &cs47l35_16bit_spi_regmap;\n+\t\t\tregmap_32bit_config = &cs47l35_32bit_spi_regmap;\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L85:\n+\tcase WM1840:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L85)) {\n+\t\t\tregmap_16bit_config = &cs47l85_16bit_spi_regmap;\n+\t\t\tregmap_32bit_config = &cs47l85_32bit_spi_regmap;\n+\t\t}\n+\t\tbreak;\n+\tcase CS47L90:\n+\tcase CS47L91:\n+\t\tif (IS_ENABLED(CONFIG_MFD_CS47L90)) {\n+\t\t\tregmap_16bit_config = &cs47l90_16bit_spi_regmap;\n+\t\t\tregmap_32bit_config = &cs47l90_32bit_spi_regmap;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(&spi->dev,\n+\t\t\t\"Unknown Madera SPI device type %ld\\n\", type);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tname = madera_name_from_type(type);\n+\n+\tif (!regmap_16bit_config) {\n+\t\tdev_err(&spi->dev,\n+\t\t\t\"Kernel does not include support for %s\\n\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmadera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);\n+\tif (!madera)\n+\t\treturn -ENOMEM;\n+\n+\tmadera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);\n+\tif (IS_ERR(madera->regmap)) {\n+\t\tret = PTR_ERR(madera->regmap);\n+\t\tdev_err(&spi->dev,\n+\t\t\t\"Failed to allocate 16-bit register map: %d\\n\",\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tmadera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);\n+\tif (IS_ERR(madera->regmap_32bit)) {\n+\t\tret = PTR_ERR(madera->regmap_32bit);\n+\t\tdev_err(&spi->dev,\n+\t\t\t\"Failed to allocate 32-bit register map: %d\\n\",\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tmadera->type = type;\n+\tmadera->type_name = name;\n+\tmadera->dev = &spi->dev;\n+\tmadera->irq = spi->irq;\n+\n+\treturn madera_dev_init(madera);\n+}\n+\n+static int madera_spi_remove(struct spi_device *spi)\n+{\n+\tstruct madera *madera = spi_get_drvdata(spi);\n+\n+\tmadera_dev_exit(madera);\n+\n+\treturn 0;\n+}\n+\n+static const struct spi_device_id madera_spi_ids[] = {\n+\t{ \"cs47l35\", CS47L35 },\n+\t{ \"cs47l85\", CS47L85 },\n+\t{ \"cs47l90\", CS47L90 },\n+\t{ \"cs47l91\", CS47L91 },\n+\t{ \"wm1840\", WM1840 },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(spi, madera_spi_ids);\n+\n+static struct spi_driver madera_spi_driver = {\n+\t.driver = {\n+\t\t.name\t= \"madera\",\n+\t\t.pm\t= &madera_pm_ops,\n+\t\t.of_match_table\t= of_match_ptr(madera_of_match),\n+\t},\n+\t.probe\t\t= madera_spi_probe,\n+\t.remove\t\t= madera_spi_remove,\n+\t.id_table\t= madera_spi_ids,\n+};\n+\n+module_spi_driver(madera_spi_driver);\n+\n+MODULE_DESCRIPTION(\"Madera SPI bus interface\");\n+MODULE_AUTHOR(\"Richard Fitzgerald <rf@opensource.wolfsonmicro.com>\");\n+MODULE_LICENSE(\"GPL v2\");\ndiff --git a/drivers/mfd/madera.h b/drivers/mfd/madera.h\nnew file mode 100644\nindex 0000000..1450b91\n--- /dev/null\n+++ b/drivers/mfd/madera.h\n@@ -0,0 +1,44 @@\n+/*\n+ * MFD internals for Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#ifndef MADERA_MFD_H\n+#define MADERA_MFD_H\n+\n+#include <linux/of.h>\n+#include <linux/pm.h>\n+\n+struct madera;\n+\n+extern const struct dev_pm_ops madera_pm_ops;\n+extern const struct of_device_id madera_of_match[];\n+\n+int madera_dev_init(struct madera *madera);\n+int madera_dev_exit(struct madera *madera);\n+\n+const char *madera_name_from_type(enum madera_type type);\n+\n+extern const struct regmap_config cs47l35_16bit_spi_regmap;\n+extern const struct regmap_config cs47l35_32bit_spi_regmap;\n+extern const struct regmap_config cs47l35_16bit_i2c_regmap;\n+extern const struct regmap_config cs47l35_32bit_i2c_regmap;\n+int cs47l35_patch(struct madera *madera);\n+\n+extern const struct regmap_config cs47l85_16bit_spi_regmap;\n+extern const struct regmap_config cs47l85_32bit_spi_regmap;\n+extern const struct regmap_config cs47l85_16bit_i2c_regmap;\n+extern const struct regmap_config cs47l85_32bit_i2c_regmap;\n+int cs47l85_patch(struct madera *madera);\n+\n+extern const struct regmap_config cs47l90_16bit_spi_regmap;\n+extern const struct regmap_config cs47l90_32bit_spi_regmap;\n+extern const struct regmap_config cs47l90_16bit_i2c_regmap;\n+extern const struct regmap_config cs47l90_32bit_i2c_regmap;\n+int cs47l90_patch(struct madera *madera);\n+#endif\ndiff --git a/include/linux/mfd/madera/core.h b/include/linux/mfd/madera/core.h\nnew file mode 100644\nindex 0000000..1a48ce9\n--- /dev/null\n+++ b/include/linux/mfd/madera/core.h\n@@ -0,0 +1,196 @@\n+/*\n+ * MFD internals for Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#ifndef MADERA_CORE_H\n+#define MADERA_CORE_H\n+\n+#include <linux/gpio/consumer.h>\n+#include <linux/interrupt.h>\n+#include <linux/irqchip/irq-madera.h>\n+#include <linux/mfd/madera/pdata.h>\n+#include <linux/notifier.h>\n+#include <linux/regmap.h>\n+#include <linux/regulator/consumer.h>\n+\n+#include <sound/madera-pdata.h>\n+\n+enum madera_type {\n+\t/* 0 is reserved for indicating failure to identify */\n+\tCS47L35 = 1,\n+\tCS47L85 = 2,\n+\tCS47L90 = 3,\n+\tCS47L91 = 4,\n+\tWM1840 = 7,\n+};\n+\n+#define MADERA_MAX_CORE_SUPPLIES\t2\n+#define MADERA_MAX_GPIOS\t\t40\n+\n+#define CS47L35_NUM_GPIOS\t\t16\n+#define CS47L85_NUM_GPIOS\t\t40\n+#define CS47L90_NUM_GPIOS\t\t38\n+\n+#define MADERA_MAX_MICBIAS\t\t4\n+\n+/* Notifier events */\n+#define MADERA_NOTIFY_VOICE_TRIGGER\t0x1\n+#define MADERA_NOTIFY_HPDET\t\t0x2\n+#define MADERA_NOTIFY_MICDET\t\t0x4\n+\n+/* GPIO Function Definitions */\n+#define MADERA_GP_FN_ALTERNATE\t\t0x00\n+#define MADERA_GP_FN_GPIO\t\t0x01\n+#define MADERA_GP_FN_DSP_GPIO\t\t0x02\n+#define MADERA_GP_FN_IRQ1\t\t0x03\n+#define MADERA_GP_FN_IRQ2\t\t0x04\n+#define MADERA_GP_FN_FLL1_CLOCK\t\t0x10\n+#define MADERA_GP_FN_FLL2_CLOCK\t\t0x11\n+#define MADERA_GP_FN_FLL3_CLOCK\t\t0x12\n+#define MADERA_GP_FN_FLLAO_CLOCK\t0x13\n+#define MADERA_GP_FN_FLL1_LOCK\t\t0x18\n+#define MADERA_GP_FN_FLL2_LOCK\t\t0x19\n+#define MADERA_GP_FN_FLL3_LOCK\t\t0x1A\n+#define MADERA_GP_FN_FLLAO_LOCK\t\t0x1B\n+#define MADERA_GP_FN_OPCLK_OUT\t\t0x40\n+#define MADERA_GP_FN_OPCLK_ASYNC_OUT\t0x41\n+#define MADERA_GP_FN_PWM1\t\t0x48\n+#define MADERA_GP_FN_PWM2\t\t0x49\n+#define MADERA_GP_FN_SPDIF_OUT\t\t0x4C\n+#define MADERA_GP_FN_HEADPHONE_DET\t0x50\n+#define MADERA_GP_FN_MIC_DET\t\t0x58\n+#define MADERA_GP_FN_DRC1_SIGNAL_DETECT\t0x80\n+#define MADERA_GP_FN_DRC2_SIGNAL_DETECT\t0x81\n+#define MADERA_GP_FN_ASRC1_IN1_LOCK\t0x88\n+#define MADERA_GP_FN_ASRC1_IN2_LOCK\t0x89\n+#define MADERA_GP_FN_ASRC2_IN1_LOCK\t0x8A\n+#define MADERA_GP_FN_ASRC2_IN2_LOCK\t0x8B\n+#define MADERA_GP_FN_DSP_IRQ1\t\t0xA0\n+#define MADERA_GP_FN_DSP_IRQ2\t\t0xA1\n+#define MADERA_GP_FN_DSP_IRQ3\t\t0xA2\n+#define MADERA_GP_FN_DSP_IRQ4\t\t0xA3\n+#define MADERA_GP_FN_DSP_IRQ5\t\t0xA4\n+#define MADERA_GP_FN_DSP_IRQ6\t\t0xA5\n+#define MADERA_GP_FN_DSP_IRQ7\t\t0xA6\n+#define MADERA_GP_FN_DSP_IRQ8\t\t0xA7\n+#define MADERA_GP_FN_DSP_IRQ9\t\t0xA8\n+#define MADERA_GP_FN_DSP_IRQ10\t\t0xA9\n+#define MADERA_GP_FN_DSP_IRQ11\t\t0xAA\n+#define MADERA_GP_FN_DSP_IRQ12\t\t0xAB\n+#define MADERA_GP_FN_DSP_IRQ13\t\t0xAC\n+#define MADERA_GP_FN_DSP_IRQ14\t\t0xAD\n+#define MADERA_GP_FN_DSP_IRQ15\t\t0xAE\n+#define MADERA_GP_FN_DSP_IRQ16\t\t0xAF\n+#define MADERA_GP_FN_HPOUT1L_SC\t\t0xB0\n+#define MADERA_GP_FN_HPOUT1R_SC\t\t0xB1\n+#define MADERA_GP_FN_HPOUT2L_SC\t\t0xB2\n+#define MADERA_GP_FN_HPOUT2R_SC\t\t0xB3\n+#define MADERA_GP_FN_HPOUT3L_SC\t\t0xB4\n+#define MADERA_GP_FN_HPOUT4R_SC\t\t0xB5\n+#define MADERA_GP_FN_SPKOUTL_SC\t\t0xB6\n+#define MADERA_GP_FN_SPKOUTR_SC\t\t0xB7\n+#define MADERA_GP_FN_HPOUT1L_ENA\t0xC0\n+#define MADERA_GP_FN_HPOUT1R_ENA\t0xC1\n+#define MADERA_GP_FN_HPOUT2L_ENA\t0xC2\n+#define MADERA_GP_FN_HPOUT2R_ENA\t0xC3\n+#define MADERA_GP_FN_HPOUT3L_ENA\t0xC4\n+#define MADERA_GP_FN_HPOUT4R_ENA\t0xC5\n+#define MADERA_GP_FN_SPKOUTL_ENA\t0xC6\n+#define MADERA_GP_FN_SPKOUTR_ENA\t0xC7\n+#define MADERA_GP_FN_HPOUT1L_DIS\t0xD0\n+#define MADERA_GP_FN_HPOUT1R_DIS\t0xD1\n+#define MADERA_GP_FN_HPOUT2L_DIS\t0xD2\n+#define MADERA_GP_FN_HPOUT2R_DIS\t0xD3\n+#define MADERA_GP_FN_HPOUT3L_DIS\t0xD4\n+#define MADERA_GP_FN_HPOUT4R_DIS\t0xD5\n+#define MADERA_GP_FN_SPKOUTL_DIS\t0xD6\n+#define MADERA_GP_FN_SPKOUTR_DIS\t0xD7\n+#define MADERA_GP_FN_SPK_SHUTDOWN\t0xE0\n+#define MADERA_GP_FN_SPK_OVH_SHUTDOWN\t0xE1\n+#define MADERA_GP_FN_SPK_OVH_WARN\t0xE2\n+#define MADERA_GP_FN_TIMER1_STATUS\t0x140\n+#define MADERA_GP_FN_TIMER2_STATUS\t0x141\n+#define MADERA_GP_FN_TIMER3_STATUS\t0x142\n+#define MADERA_GP_FN_TIMER4_STATUS\t0x143\n+#define MADERA_GP_FN_TIMER5_STATUS\t0x144\n+#define MADERA_GP_FN_TIMER6_STATUS\t0x145\n+#define MADERA_GP_FN_TIMER7_STATUS\t0x146\n+#define MADERA_GP_FN_TIMER8_STATUS\t0x147\n+#define MADERA_GP_FN_EVENTLOG1_FIFO_STS\t0x150\n+#define MADERA_GP_FN_EVENTLOG2_FIFO_STS\t0x151\n+#define MADERA_GP_FN_EVENTLOG3_FIFO_STS\t0x152\n+#define MADERA_GP_FN_EVENTLOG4_FIFO_STS\t0x153\n+#define MADERA_GP_FN_EVENTLOG5_FIFO_STS\t0x154\n+#define MADERA_GP_FN_EVENTLOG6_FIFO_STS\t0x155\n+#define MADERA_GP_FN_EVENTLOG7_FIFO_STS\t0x156\n+#define MADERA_GP_FN_EVENTLOG8_FIFO_STS\t0x157\n+\n+struct snd_soc_dapm_context;\n+\n+/*\n+ * struct madera - internal data shared by the set of Madera drivers\n+ *\n+ * This should not be used by anything except child drivers of the Madera MFD\n+ *\n+ * @regmap:\t\tpointer to the regmap instance for 16-bit registers\n+ * @regmap_32bit:\tpointer to the regmap instance for 32-bit registers\n+ * @dev:\t\tpointer to the MFD device\n+ * @type:\t\ttype of codec\n+ * @rev:\t\tsilicon revision\n+ * @type_name:\t\tdisplay name of this codec\n+ * @reset_gpio:\t\tgpio controlling the reset line\n+ * @num_core_supplies:\tnumber of core supply regulators\n+ * @core_supplies:\tlist of core supplies that are always required\n+ * @dcvdd:\t\tpointer to DCVDD regulator\n+ * @internal_dcvdd:\ttrue if DCVDD is supplied from the internal LDO1\n+ * @pdata:\t\tour pdata\n+ * @irq_dev:\t\tthe irqchip child driver device\n+ * @irq:\t\thost irq number from SPI or I2C configuration\n+ * @out_clamp:\t\tindicates output clamp state for each analogue output\n+ * @out_shorted:\tindicates short circuit state for each analogue output\n+ * @hp_ena:\t\tbitflags of enable state for the headphone outputs\n+ * @num_micbias:\tnumber of MICBIAS outputs\n+ * @num_childbias:\tnumber of child biases for each MICBIAS\n+ * @dapm:\t\tpointer to codec driver DAPM context\n+ * @notifier:\t\tnotifier for signalling events to ASoC machine driver\n+ */\n+struct madera {\n+\tstruct regmap *regmap;\n+\tstruct regmap *regmap_32bit;\n+\n+\tstruct device *dev;\n+\n+\tenum madera_type type;\n+\tunsigned int rev;\n+\tconst char *type_name;\n+\n+\tstruct gpio_desc *reset_gpio;\n+\n+\tint num_core_supplies;\n+\tstruct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES];\n+\tstruct regulator *dcvdd;\n+\tbool internal_dcvdd;\n+\n+\tstruct madera_pdata pdata;\n+\n+\tstruct device *irq_dev;\n+\tint irq;\n+\n+\tunsigned int out_clamp[MADERA_MAX_OUTPUT];\n+\tunsigned int out_shorted[MADERA_MAX_OUTPUT];\n+\tunsigned int hp_ena;\n+\n+\tunsigned int num_micbias;\n+\tunsigned int num_childbias[MADERA_MAX_MICBIAS];\n+\n+\tstruct snd_soc_dapm_context *dapm;\n+\n+\tstruct blocking_notifier_head notifier;\n+};\n+#endif\ndiff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h\nnew file mode 100644\nindex 0000000..6b09fdb\n--- /dev/null\n+++ b/include/linux/mfd/madera/pdata.h\n@@ -0,0 +1,61 @@\n+/*\n+ * Platform data for Cirrus Logic Madera codecs\n+ *\n+ * Copyright 2015-2017 Cirrus Logic\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2 as\n+ * published by the Free Software Foundation.\n+ */\n+\n+#ifndef MADERA_PDATA_H\n+#define MADERA_PDATA_H\n+\n+#include <linux/irqchip/irq-madera-pdata.h>\n+#include <linux/kernel.h>\n+#include <linux/regulator/arizona-ldo1.h>\n+#include <linux/regulator/arizona-micsupp.h>\n+#include <linux/regulator/machine.h>\n+#include <sound/madera-pdata.h>\n+\n+#define MADERA_MAX_MICBIAS\t\t4\n+#define MADERA_MAX_CHILD_MICBIAS\t4\n+\n+#define MADERA_MAX_GPSW\t\t\t2\n+\n+struct pinctrl_map;\n+\n+/**\n+ * struct madera_pdata - Configuration data for Madera devices\n+ *\n+ * @reset:\t    GPIO controlling /RESET (0 = none)\n+ * @ldo1:\t    Substruct of pdata for the LDO1 regulator\n+ * @micvdd:\t    Substruct of pdata for the MICVDD regulator\n+ * @irqchip:\t    Substruct of pdata for the irqchip driver\n+ * @gpio_base:\t    Base GPIO number\n+ * @gpio_configs:   Array of GPIO configurations (See Documentation/pinctrl.txt)\n+ * @n_gpio_configs: Number of entries in gpio_configs\n+ * @codec:\t    Substructure of pdata for the ASoC codec driver\n+ *\t\t    See include/sound/madera-pdata.h\n+ * @gpsw:\t    General purpose switch mode setting (See the SW1_MODE field\n+ *\t\t    in the datasheet for the available values for your codec)\n+ */\n+struct madera_pdata {\n+\tint reset;\n+\n+\tstruct arizona_ldo1_pdata ldo1;\n+\tstruct arizona_micsupp_pdata micvdd;\n+\n+\tstruct madera_irqchip_pdata irqchip;\n+\n+\tint gpio_base;\n+\n+\tconst struct pinctrl_map *gpio_configs;\n+\tint n_gpio_configs;\n+\n+\tstruct madera_codec_pdata codec;\n+\n+\tu32 gpsw[MADERA_MAX_GPSW];\n+};\n+\n+#endif\n",
    "prefixes": [
        "v5",
        "03/17"
    ]
}