Devicetree
 help / color / mirror / Atom feed
* Applied "spi-imx: Implements handling of the SPI_READY mode flag." to the spi tree
From: Mark Brown @ 2017-04-25 15:46 UTC (permalink / raw)
  To: Leif Middelschulte; +Cc: Leif Middelschulte, Mark Brown
In-Reply-To: <20170423191958.32724-1-Leif.Middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

The patch

   spi-imx: Implements handling of the SPI_READY mode flag.

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From f72efa7e690ab5c4068ccba31c4da032bc45c29c Mon Sep 17 00:00:00 2001
From: Leif Middelschulte <leif.middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Sun, 23 Apr 2017 21:19:58 +0200
Subject: [PATCH] spi-imx: Implements handling of the SPI_READY mode flag.

This patch implements consideration of the SPI_READY mode flag as
defined in spi.h. It extends the device tree bindings to support
the values defined by the reference manual for the DRCTL field.

Thus supporting edge-triggered and level-triggered bursts.

Signed-off-by: Leif Middelschulte <Leif.Middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/spi/fsl-imx-cspi.txt         |  7 +++++++
 drivers/spi/spi-imx.c                                | 20 ++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
index 8bc95e2fc47f..31b5b21598ff 100644
--- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -23,6 +23,12 @@ See the clock consumer binding,
 Obsolete properties:
 - fsl,spi-num-chipselects : Contains the number of the chipselect
 
+Optional properties:
+- fsl,spi-rdy-drctl: Integer, representing the value of DRCTL, the register
+controlling the SPI_READY handling. Note that to enable the DRCTL consideration,
+the SPI_READY mode-flag needs to be set too.
+Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst).
+
 Example:
 
 ecspi@70010000 {
@@ -35,4 +41,5 @@ ecspi@70010000 {
 		   <&gpio3 25 0>; /* GPIO3_25 */
 	dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
 	dma-names = "rx", "tx";
+	fsl,spi-rdy-drctl = <1>;
 };
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9a7c62f471dc..b402530a7a9a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -95,6 +95,7 @@ struct spi_imx_data {
 	unsigned int spi_bus_clk;
 
 	unsigned int bytes_per_word;
+	unsigned int spi_drctl;
 
 	unsigned int count;
 	void (*tx)(struct spi_imx_data *);
@@ -246,6 +247,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_CTRL_XCH		(1 <<  2)
 #define MX51_ECSPI_CTRL_SMC		(1 << 3)
 #define MX51_ECSPI_CTRL_MODE_MASK	(0xf << 4)
+#define MX51_ECSPI_CTRL_DRCTL(drctl)	((drctl) << 16)
 #define MX51_ECSPI_CTRL_POSTDIV_OFFSET	8
 #define MX51_ECSPI_CTRL_PREDIV_OFFSET	12
 #define MX51_ECSPI_CTRL_CS(cs)		((cs) << 18)
@@ -355,6 +357,12 @@ static int mx51_ecspi_config(struct spi_device *spi,
 	 */
 	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
+	/*
+	 * Enable SPI_RDY handling (falling edge/level triggered).
+	 */
+	if (spi->mode & SPI_READY)
+		ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
+
 	/* set clock speed */
 	ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk);
 	spi_imx->spi_bus_clk = clk;
@@ -1173,7 +1181,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct spi_imx_data *spi_imx;
 	struct resource *res;
-	int i, ret, irq;
+	int i, ret, irq, spi_drctl;
 
 	if (!np && !mxc_platform_info) {
 		dev_err(&pdev->dev, "can't get the platform data\n");
@@ -1181,6 +1189,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+	ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl);
+	if ((ret < 0) || (spi_drctl >= 0x3)) {
+		/* '11' is reserved */
+		spi_drctl = 0;
+	}
+
 	if (!master)
 		return -ENOMEM;
 
@@ -1216,7 +1230,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
 	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx))
-		spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
+		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
+
+	spi_imx->spi_drctl = spi_drctl;
 
 	init_completion(&spi_imx->xfer_done);
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH v2 15/18] dt-bindings: sound: Add bindings for Cirrus Logic Madera codecs
From: Mark Brown @ 2017-04-25 15:52 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: gnurou, alsa-devel, jason, devicetree, linus.walleij, patches,
	linux-kernel, linux-gpio, robh+dt, tglx, lee.jones
In-Reply-To: <1493050124-5970-16-git-send-email-rf@opensource.wolfsonmicro.com>


[-- Attachment #1.1: Type: text/plain, Size: 1090 bytes --]

On Mon, Apr 24, 2017 at 05:08:41PM +0100, Richard Fitzgerald wrote:
> The Cirrus Logic Madera codecs are a family of related codecs with
> extensive digital and analogue I/O, digital mixing and routing,
> signal processing and programmable DSPs.

Please submit patches using subject lines reflecting the style for the
subsystem.  This makes it easier for people to identify relevant
patches.  Look at what existing commits in the area you're changing are
doing and make sure your subject lines visually resemble what they're
doing.

> +Required properties:
> +  - compatible : One of the following chip-specific strings:
> +        "cirrus,cs47l35-codec"
> +        "cirrus,cs47l85-codec"
> +        "cirrus,cs47l90-codec"

You shouldn't have compatible strings for subfunctions of a MFD unless
these represent meaningful reusable IPs that can exist separately from
the parent chip, that's clearly not the case here.  All you're doing
here is encoding Linux internal abstractions which aren't OS neutral and
might change in future (for example clocking might move more into the
clock API).

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Re: [PATCH 2/2] fpga: lattice machxo2: Add Lattice MachXO2 support
From: Alan Tull @ 2017-04-25 15:59 UTC (permalink / raw)
  To: Paolo Pisati
  Cc: Rob Herring, Mark Rutland, Alan Tull, Moritz Fischer,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA, linux-kernel
In-Reply-To: <1492960845-342-3-git-send-email-p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Sun, Apr 23, 2017 at 10:20 AM, Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hi Paolo,

Thanks for submitting your driver.  A few things...

> Add support for the Lattice MachXO2 FPGA chip in Slave SPI configuration.
>

Please add a bit of a description here.  Format should be subject
line, skip a line,  description, skip a line, then your signoff.

> Signed-off-by: Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/fpga/Kconfig       |   7 ++
>  drivers/fpga/Makefile      |   1 +
>  drivers/fpga/machxo2-spi.c | 199 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 207 insertions(+)
>  create mode 100644 drivers/fpga/machxo2-spi.c
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index c81cb7d..cce135b 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -26,6 +26,13 @@ config FPGA_MGR_ICE40_SPI
>         help
>           FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
>
> +config FPGA_MGR_MACHXO2_SPI
> +       tristate "Lattice MachXO2 SPI"
> +       depends on SPI
> +       help
> +        FPGA manager driver support for Lattice MachXO2 configuration
> +        over slave SPI interface.
> +
>  config FPGA_MGR_SOCFPGA
>         tristate "Altera SOCFPGA FPGA Manager"
>         depends on ARCH_SOCFPGA || COMPILE_TEST
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index c6f5d74..cdab1fe 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_FPGA)                      += fpga-mgr.o
>
>  # FPGA Manager Drivers
>  obj-$(CONFIG_FPGA_MGR_ICE40_SPI)       += ice40-spi.o
> +obj-$(CONFIG_FPGA_MGR_MACHXO2_SPI)     += machxo2-spi.o
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA)         += socfpga.o
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)     += socfpga-a10.o
>  obj-$(CONFIG_FPGA_MGR_TS73XX)          += ts73xx-fpga.o
> diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c
> new file mode 100644
> index 0000000..5ee56bd
> --- /dev/null
> +++ b/drivers/fpga/machxo2-spi.c
> @@ -0,0 +1,199 @@
> +/**
> + * Lattice MachXO2 Slave SPI Driver
> + *
> + * Copyright (C) 2017 Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * Manage Lattice FPGA firmware that is loaded over SPI using
> + * the slave serial configuration interface.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/spi/spi.h>
> +
> +

Please run checkpatch and fix whatever it points out, such as not to
use double blank lines.

> +/* MachXO2 Programming Guide - sysCONFIG Programming Commands */
> +
> +#define ISC_ENABLE             0x000008c6
> +#define ISC_ERASE              0x0000040e
> +#define ISC_PROGRAMDONE                0x0000005e
> +#define LSC_CHECKBUSY          0x000000f0
> +#define LSC_INITADDRESS                0x00000046
> +#define LSC_PROGINCRNV         0x01000070
> +#define LSC_REFRESH            0x00000079
> +
> +/*
> + * Max CCLK in Slave SPI mode according to 'MachXO2 Family Data
> + * Sheet' sysCONFIG Port Timing Specifications (3-36)
> + */
> +#define MACHXO2_MAX_SPEED      66000000
> +
> +#define MACHXO2_LOW_DELAY      5       /* us */
> +#define MACHXO2_HIGH_DELAY     200     /* us */
> +
> +#define MACHXO2_OP_SIZE                sizeof(uint32_t)
> +#define MACHXO2_PAGE_SIZE      16
> +#define MACHXO2_BUF_SIZE       (MACHXO2_OP_SIZE + MACHXO2_PAGE_SIZE)
> +
> +
> +static int waituntilnotbusy(struct spi_device *spi)

Could you rename to something like wait_until_not_busy?

> +{
> +       uint8_t rx, busyflag = 0x80;

Please create a macro for the 0x80 value and use it here.

> +       uint32_t checkbusy = LSC_CHECKBUSY;

Another checkpatch: u32 is preferred over uint32_t.

> +
> +       do {
> +               if (spi_write_then_read(spi, &checkbusy, MACHXO2_OP_SIZE,
> +                                         &rx, sizeof(rx)))
> +                       return -EIO;

Please pass down the spi_write_then_read error code like:

ret = spi_write_then_read(...);
if (ret)
        return ret;

There's a few places below where I will point that out for spi_write as well.

> +       } while (rx & busyflag);

Skip a line before the return.

> +       return 0;
> +}
> +
> +static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr)
> +{
> +       return FPGA_MGR_STATE_UNKNOWN;
> +}
> +
> +static int machxo2_write_init(struct fpga_manager *mgr,
> +                             struct fpga_image_info *info,
> +                             const char *buf, size_t count)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t enable = ISC_ENABLE;
> +       uint32_t erase = ISC_ERASE;
> +       uint32_t initaddr = LSC_INITADDRESS;
> +
> +       if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
> +               dev_err(&mgr->dev,
> +                       "Partial reconfiguration is not supported\n");
> +               return -ENOTSUPP;
> +       }
> +
> +       if (spi_write(spi, &enable, MACHXO2_OP_SIZE))
> +               goto fail;

Please skip a line here.

> +       udelay(MACHXO2_LOW_DELAY);
> +       if (spi_write(spi, &erase, MACHXO2_OP_SIZE))
> +               goto fail;

Again, it's better to pass the spi_write error code.

ret = spi_write(...)
if (ret)
     goto fail;

Then skip a line.

> +       waituntilnotbusy(spi);
> +       if (spi_write(spi, &initaddr, MACHXO2_OP_SIZE))
> +               goto fail;

Pass through the error code, same as above.

> +       return 0;
> +
> +fail:
> +       dev_err(&mgr->dev, "Error during FPGA init.\n");
> +       return -EIO;

return ret;

> +}
> +
> +static int machxo2_write(struct fpga_manager *mgr, const char *buf,
> +                        size_t count)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t progincr = LSC_PROGINCRNV;
> +       uint8_t payload[MACHXO2_BUF_SIZE];
> +       int i;
> +
> +       if (count % MACHXO2_PAGE_SIZE != 0) {
> +               dev_err(&mgr->dev, "Malformed payload.\n");
> +               return -EINVAL;
> +       }
> +
> +       memcpy(payload, &progincr, MACHXO2_OP_SIZE);
> +       for (i = 0; i < count; i += MACHXO2_PAGE_SIZE) {
> +               memcpy(&payload[MACHXO2_OP_SIZE], &buf[i], MACHXO2_PAGE_SIZE);
> +               if (spi_write(spi, payload, MACHXO2_BUF_SIZE)) {
> +                       dev_err(&mgr->dev, "Error loading the bitstream.\n");
> +                       return -EIO;

Pass through spi_write error code.

> +               }
> +               udelay(MACHXO2_HIGH_DELAY);
> +       }
> +
> +       return 0;
> +}
> +
> +static int machxo2_write_complete(struct fpga_manager *mgr,
> +                                 struct fpga_image_info *info)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t progdone = ISC_PROGRAMDONE;
> +       uint32_t refresh = LSC_REFRESH;
> +
> +       if (spi_write(spi, &progdone, MACHXO2_OP_SIZE))
> +               goto fail;

Pass spi_write error code if error.  And skip a line.

> +       /* yep, LSC_REFRESH is 3 bytes long actually */
> +       if (spi_write(spi, &refresh, MACHXO2_OP_SIZE-1))
> +               goto fail;

Here too.  Also add spaces around the minus sign.

> +       return 0;
> +
> +fail:
> +       dev_err(&mgr->dev, "Refresh failed.\n");
> +       return -EIO;

Will be return ret;

> +}
> +
> +static const struct fpga_manager_ops machxo2_ops = {
> +       .state = machxo2_spi_state,
> +       .write_init = machxo2_write_init,
> +       .write = machxo2_write,
> +       .write_complete = machxo2_write_complete,
> +};
> +
> +static int machxo2_spi_probe(struct spi_device *spi)
> +{
> +       struct device *dev = &spi->dev;
> +       int ret = 0;
> +
> +       if (spi->max_speed_hz > MACHXO2_MAX_SPEED) {
> +               dev_err(dev, "Speed is too high\n");
> +               return -EINVAL;
> +       }
> +
> +       ret =  fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
> +                                &machxo2_ops, spi);
> +       if (ret)
> +               dev_err(dev, "Unable to register FPGA manager");

You can just 'return fpga_mgr_register(...);' here.

> +
> +       return ret;
> +}
> +
> +static int machxo2_spi_remove(struct spi_device *spi)
> +{
> +       struct device *dev = &spi->dev;
> +
> +       fpga_mgr_unregister(dev);

Skip  a line.

> +       return 0;
> +}
> +
> +static const struct of_device_id of_match[] = {
> +       { .compatible = "lattice,machxo2-slave-spi", },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, of_match);
> +
> +static const struct spi_device_id lattice_ids[] = {
> +       { "machxo2-slave-spi", 0 },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(spi, lattice_ids);
> +
> +static struct spi_driver machxo2_spi_driver = {
> +       .driver = {
> +               .name = "machxo2-slave-spi",
> +               .owner = THIS_MODULE,

You don't need to specify THIS_MODULE here.  spi_register_driver will
add that for you.

> +               .of_match_table = of_match_ptr(of_match),
> +       },
> +       .probe = machxo2_spi_probe,
> +       .remove = machxo2_spi_remove,
> +       .id_table = lattice_ids,
> +};
> +
> +module_spi_driver(machxo2_spi_driver)
> +
> +MODULE_AUTHOR("Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
> +MODULE_DESCRIPTION("Load Lattice FPGA firmware over SPI");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Thanks,
Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Ryan Lee @ 2017-04-25 16:24 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
	Kuninori Morimoto, Arnd Bergmann,
	ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	lars-Qo5EllUWu/uELgA04lAiVw, bardliao-Rasf1IRRPZFBDgjK7y7TUQ,
	nh6z-fFIq/eER6g8, KCHSU0-KrzQf0k3Iz9BDgjK7y7TUQ, Axel Lin,
	romain.perier-ZGY8ohtN/8qB+jHODAdFcQ, Srinivas Kandagatla,
	oder_chiou-Rasf1IRRPZFBDgjK7y7TUQ,
	Paul.Handrigan-jGc1dHjMKG3QT0dZR+AlfA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dylan Reid
In-Reply-To: <E1cwCZ1-0001o4-Q5@debutante>

I was not able to see any activities about MAX98927 driver after previous mail.
Is there anything wrong with this driver?


On Thu, Apr 6, 2017 at 11:55 AM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> The patch
>
>    ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> has been applied to the asoc tree at
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
>
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.
>
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
>
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
>
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.
>
> Thanks,
> Mark
>
> From 7c0c2000716e64151b3c0c62026c18f31537ebe9 Mon Sep 17 00:00:00 2001
> From: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> Date: Tue, 4 Apr 2017 02:23:08 +0900
> Subject: [PATCH] ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> Signed-off-by: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  .../devicetree/bindings/sound/max98925.txt         |  22 -
>  .../devicetree/bindings/sound/max98926.txt         |  32 -
>  .../devicetree/bindings/sound/max9892x.txt         |  41 +
>  sound/soc/codecs/Kconfig                           |   5 +
>  sound/soc/codecs/Makefile                          |   2 +
>  sound/soc/codecs/max98927.c                        | 841 +++++++++++++++++++++
>  sound/soc/codecs/max98927.h                        | 272 +++++++
>  7 files changed, 1161 insertions(+), 54 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98925.txt
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98926.txt
>  create mode 100644 Documentation/devicetree/bindings/sound/max9892x.txt
>  create mode 100644 sound/soc/codecs/max98927.c
>  create mode 100644 sound/soc/codecs/max98927.h
>
> diff --git a/Documentation/devicetree/bindings/sound/max98925.txt b/Documentation/devicetree/bindings/sound/max98925.txt
> deleted file mode 100644
> index 27be63e2aa0d..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98925.txt
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -max98925 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98925"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98925@1a {
> -       compatible = "maxim,max98925";
> -       vmon-slot-no = <0>;
> -       imon-slot-no = <2>;
> -       reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt
> deleted file mode 100644
> index 0b7f4e4d5f9a..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98926.txt
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -max98926 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98926"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -                   or in inteleave mode this will be used as
> -                   interleave slot.
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - interleave-mode : When using two MAX98926 in a system it is
> -                      possible to create ADC data that that will
> -                      overflow the frame size. Digital Audio Interleave
> -                      mode provides a means to output VMON and IMON data
> -                      from two devices on a single DOUT line when running
> -                      smaller frames sizes such as 32 BCLKS per LRCLK or
> -                      48 BCLKS per LRCLK.
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98926@1a {
> -   compatible = "maxim,max98926";
> -   vmon-slot-no = <0>;
> -   imon-slot-no = <2>;
> -   reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max9892x.txt b/Documentation/devicetree/bindings/sound/max9892x.txt
> new file mode 100644
> index 000000000000..f6171591ddc6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/max9892x.txt
> @@ -0,0 +1,41 @@
> +Maxim Integrated MAX98925/MAX98926/MAX98927 Speaker Amplifier
> +
> +This device supports I2C.
> +
> +Required properties:
> +
> +  - compatible : should be one of the following
> +    - "maxim,max98925"
> +    - "maxim,max98926"
> +    - "maxim,max98927"
> +
> +  - vmon-slot-no : slot number used to send voltage information
> +                   or in inteleave mode this will be used as
> +                   interleave slot.
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - imon-slot-no : slot number used to send current information
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - interleave-mode : When using two MAX9892X in a system it is
> +                   possible to create ADC data that that will
> +                   overflow the frame size. Digital Audio Interleave
> +                   mode provides a means to output VMON and IMON data
> +                   from two devices on a single DOUT line when running
> +                   smaller frames sizes such as 32 BCLKS per LRCLK or
> +                   48 BCLKS per LRCLK.
> +                   Range : 0 (off), 1 (on),  Default : 0
> +
> +  - reg : the I2C address of the device for I2C
> +
> +Example:
> +
> +codec: max98927@3a {
> +   compatible = "maxim,max98927";
> +   vmon-slot-no = <0>;
> +   imon-slot-no = <1>;
> +   interleave-mode = <0>;
> +   reg = <0x3a>;
> +};
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 9e1718a8cb1c..65e31ab88280 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -89,6 +89,7 @@ config SND_SOC_ALL_CODECS
>         select SND_SOC_MAX9867 if I2C
>         select SND_SOC_MAX98925 if I2C
>         select SND_SOC_MAX98926 if I2C
> +       select SND_SOC_MAX98927 if I2C
>         select SND_SOC_MAX9850 if I2C
>         select SND_SOC_MAX9860 if I2C
>         select SND_SOC_MAX9768 if I2C
> @@ -585,6 +586,10 @@ config SND_SOC_MAX98925
>  config SND_SOC_MAX98926
>         tristate
>
> +config SND_SOC_MAX98927
> +       tristate "Maxim Integrated MAX98927 Speaker Amplifier"
> +       depends on I2C
> +
>  config SND_SOC_MAX9850
>         tristate
>
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 7e1dad79610b..64656c43200c 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -84,6 +84,7 @@ snd-soc-max98371-objs := max98371.o
>  snd-soc-max9867-objs := max9867.o
>  snd-soc-max98925-objs := max98925.o
>  snd-soc-max98926-objs := max98926.o
> +snd-soc-max98927-objs := max98927.o
>  snd-soc-max9850-objs := max9850.o
>  snd-soc-max9860-objs := max9860.o
>  snd-soc-mc13783-objs := mc13783.o
> @@ -312,6 +313,7 @@ obj-$(CONFIG_SND_SOC_MAX98357A)     += snd-soc-max98357a.o
>  obj-$(CONFIG_SND_SOC_MAX9867)  += snd-soc-max9867.o
>  obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
>  obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
> +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
>  obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
>  obj-$(CONFIG_SND_SOC_MAX9860)  += snd-soc-max9860.o
>  obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
> diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c
> new file mode 100644
> index 000000000000..b5ee29499e16
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.c
> @@ -0,0 +1,841 @@
> +/*
> + * max98927.c  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright (C) 2016 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <sound/tlv.h>
> +#include "max98927.h"
> +
> +static struct reg_default max98927_reg[] = {
> +       {MAX98927_R0001_INT_RAW1,  0x00},
> +       {MAX98927_R0002_INT_RAW2,  0x00},
> +       {MAX98927_R0003_INT_RAW3,  0x00},
> +       {MAX98927_R0004_INT_STATE1,  0x00},
> +       {MAX98927_R0005_INT_STATE2,  0x00},
> +       {MAX98927_R0006_INT_STATE3,  0x00},
> +       {MAX98927_R0007_INT_FLAG1,  0x00},
> +       {MAX98927_R0008_INT_FLAG2,  0x00},
> +       {MAX98927_R0009_INT_FLAG3,  0x00},
> +       {MAX98927_R000A_INT_EN1,  0x00},
> +       {MAX98927_R000B_INT_EN2,  0x00},
> +       {MAX98927_R000C_INT_EN3,  0x00},
> +       {MAX98927_R000D_INT_FLAG_CLR1,  0x00},
> +       {MAX98927_R000E_INT_FLAG_CLR2,  0x00},
> +       {MAX98927_R000F_INT_FLAG_CLR3,  0x00},
> +       {MAX98927_R0010_IRQ_CTRL,  0x00},
> +       {MAX98927_R0011_CLK_MON,  0x00},
> +       {MAX98927_R0012_WDOG_CTRL,  0x00},
> +       {MAX98927_R0013_WDOG_RST,  0x00},
> +       {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH,  0x00},
> +       {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH,  0x00},
> +       {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS,  0x00},
> +       {MAX98927_R0017_PIN_CFG,  0x55},
> +       {MAX98927_R0018_PCM_RX_EN_A,  0x00},
> +       {MAX98927_R0019_PCM_RX_EN_B,  0x00},
> +       {MAX98927_R001A_PCM_TX_EN_A,  0x00},
> +       {MAX98927_R001B_PCM_TX_EN_B,  0x00},
> +       {MAX98927_R001C_PCM_TX_HIZ_CTRL_A,  0x00},
> +       {MAX98927_R001D_PCM_TX_HIZ_CTRL_B,  0x00},
> +       {MAX98927_R001E_PCM_TX_CH_SRC_A,  0x00},
> +       {MAX98927_R001F_PCM_TX_CH_SRC_B,  0x00},
> +       {MAX98927_R0020_PCM_MODE_CFG,  0x40},
> +       {MAX98927_R0021_PCM_MASTER_MODE,  0x00},
> +       {MAX98927_R0022_PCM_CLK_SETUP,  0x22},
> +       {MAX98927_R0023_PCM_SR_SETUP1,  0x00},
> +       {MAX98927_R0024_PCM_SR_SETUP2,  0x00},
> +       {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,  0x00},
> +       {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,  0x00},
> +       {MAX98927_R0027_ICC_RX_EN_A,  0x00},
> +       {MAX98927_R0028_ICC_RX_EN_B,  0x00},
> +       {MAX98927_R002B_ICC_TX_EN_A,  0x00},
> +       {MAX98927_R002C_ICC_TX_EN_B,  0x00},
> +       {MAX98927_R002E_ICC_HIZ_MANUAL_MODE,  0x00},
> +       {MAX98927_R002F_ICC_TX_HIZ_EN_A,  0x00},
> +       {MAX98927_R0030_ICC_TX_HIZ_EN_B,  0x00},
> +       {MAX98927_R0031_ICC_LNK_EN,  0x00},
> +       {MAX98927_R0032_PDM_TX_EN,  0x00},
> +       {MAX98927_R0033_PDM_TX_HIZ_CTRL,  0x00},
> +       {MAX98927_R0034_PDM_TX_CTRL,  0x00},
> +       {MAX98927_R0035_PDM_RX_CTRL,  0x00},
> +       {MAX98927_R0036_AMP_VOL_CTRL,  0x00},
> +       {MAX98927_R0037_AMP_DSP_CFG,  0x02},
> +       {MAX98927_R0038_TONE_GEN_DC_CFG,  0x00},
> +       {MAX98927_R0039_DRE_CTRL,  0x01},
> +       {MAX98927_R003A_AMP_EN,  0x00},
> +       {MAX98927_R003B_SPK_SRC_SEL,  0x00},
> +       {MAX98927_R003C_SPK_GAIN,  0x00},
> +       {MAX98927_R003D_SSM_CFG,  0x01},
> +       {MAX98927_R003E_MEAS_EN,  0x00},
> +       {MAX98927_R003F_MEAS_DSP_CFG,  0x04},
> +       {MAX98927_R0040_BOOST_CTRL0,  0x00},
> +       {MAX98927_R0041_BOOST_CTRL3,  0x00},
> +       {MAX98927_R0042_BOOST_CTRL1,  0x00},
> +       {MAX98927_R0043_MEAS_ADC_CFG,  0x00},
> +       {MAX98927_R0044_MEAS_ADC_BASE_MSB,  0x00},
> +       {MAX98927_R0045_MEAS_ADC_BASE_LSB,  0x00},
> +       {MAX98927_R0046_ADC_CH0_DIVIDE,  0x00},
> +       {MAX98927_R0047_ADC_CH1_DIVIDE,  0x00},
> +       {MAX98927_R0048_ADC_CH2_DIVIDE,  0x00},
> +       {MAX98927_R0049_ADC_CH0_FILT_CFG,  0x00},
> +       {MAX98927_R004A_ADC_CH1_FILT_CFG,  0x00},
> +       {MAX98927_R004B_ADC_CH2_FILT_CFG,  0x00},
> +       {MAX98927_R004C_MEAS_ADC_CH0_READ,  0x00},
> +       {MAX98927_R004D_MEAS_ADC_CH1_READ,  0x00},
> +       {MAX98927_R004E_MEAS_ADC_CH2_READ,  0x00},
> +       {MAX98927_R0051_BROWNOUT_STATUS,  0x00},
> +       {MAX98927_R0052_BROWNOUT_EN,  0x00},
> +       {MAX98927_R0053_BROWNOUT_INFINITE_HOLD,  0x00},
> +       {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR,  0x00},
> +       {MAX98927_R0055_BROWNOUT_LVL_HOLD,  0x00},
> +       {MAX98927_R005A_BROWNOUT_LVL1_THRESH,  0x00},
> +       {MAX98927_R005B_BROWNOUT_LVL2_THRESH,  0x00},
> +       {MAX98927_R005C_BROWNOUT_LVL3_THRESH,  0x00},
> +       {MAX98927_R005D_BROWNOUT_LVL4_THRESH,  0x00},
> +       {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS,  0x00},
> +       {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL,  0x00},
> +       {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL,  0x00},
> +       {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE,  0x00},
> +       {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT,  0x00},
> +       {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT,  0x00},
> +       {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT,  0x00},
> +       {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1,  0x00},
> +       {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2,  0x00},
> +       {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT,  0x00},
> +       {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,  0x00},
> +       {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY,  0x00},
> +       {MAX98927_R0084_ENV_TRACK_REL_RATE,  0x00},
> +       {MAX98927_R0085_ENV_TRACK_HOLD_RATE,  0x00},
> +       {MAX98927_R0086_ENV_TRACK_CTRL,  0x00},
> +       {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,  0x00},
> +       {MAX98927_R00FF_GLOBAL_SHDN,  0x00},
> +       {MAX98927_R0100_SOFT_RESET,  0x00},
> +       {MAX98927_R01FF_REV_ID,  0x40},
> +};
> +
> +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
> +{
> +       struct snd_soc_codec *codec = codec_dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int mode = 0;
> +       unsigned int format = 0;
> +       unsigned int invert = 0;
> +
> +       dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
> +
> +       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +       case SND_SOC_DAIFMT_CBS_CFS:
> +               mode = MAX98927_PCM_MASTER_MODE_SLAVE;
> +               break;
> +       case SND_SOC_DAIFMT_CBM_CFM:
> +               max98927->master = true;
> +               mode = MAX98927_PCM_MASTER_MODE_MASTER;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI clock mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0021_PCM_MASTER_MODE,
> +               MAX98927_PCM_MASTER_MODE_MASK,
> +               mode);
> +
> +       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +       case SND_SOC_DAIFMT_NB_NF:
> +               break;
> +       case SND_SOC_DAIFMT_IB_NF:
> +               invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI invert mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE,
> +               invert);
> +
> +       /* interface format */
> +       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +       case SND_SOC_DAIFMT_I2S:
> +               max98927->iface |= SND_SOC_DAIFMT_I2S;
> +               format = MAX98927_PCM_FORMAT_I2S;
> +               break;
> +       case SND_SOC_DAIFMT_LEFT_J:
> +               max98927->iface |= SND_SOC_DAIFMT_LEFT_J;
> +               format = MAX98927_PCM_FORMAT_LJ;
> +               break;
> +       case SND_SOC_DAIFMT_PDM:
> +               max98927->iface |= SND_SOC_DAIFMT_PDM;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       /* pcm channel configuration */
> +       if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0020_PCM_MODE_CFG,
> +                       MAX98927_PCM_MODE_CFG_FORMAT_MASK,
> +                       format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 0);
> +
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);
> +
> +       /* pdm channel configuration */
> +       if (max98927->iface & SND_SOC_DAIFMT_PDM) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 1);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 3);
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 0);
> +       return 0;
> +}
> +
> +/* codec MCLK rate in master mode */
> +static const int rate_table[] = {
> +       5644800, 6000000, 6144000, 6500000,
> +       9600000, 11289600, 12000000, 12288000,
> +       13000000, 19200000,
> +};
> +
> +static int max98927_set_clock(struct max98927_priv *max98927,
> +       struct snd_pcm_hw_params *params)
> +{
> +       struct snd_soc_codec *codec = max98927->codec;
> +       /* BCLK/LRCLK ratio calculation */
> +       int blr_clk_ratio = params_channels(params) * max98927->ch_size;
> +       int value;
> +
> +       if (max98927->master) {
> +               int i;
> +               /* match rate to closest value */
> +               for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
> +                       if (rate_table[i] >= max98927->sysclk)
> +                               break;
> +               }
> +               if (i == ARRAY_SIZE(rate_table)) {
> +                       dev_err(codec->dev, "failed to find proper clock rate.\n");
> +                       return -EINVAL;
> +               }
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0021_PCM_MASTER_MODE,
> +                       MAX98927_PCM_MASTER_MODE_MCLK_MASK,
> +                       i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
> +       }
> +
> +       switch (blr_clk_ratio) {
> +       case 32:
> +               value = 2;
> +               break;
> +       case 48:
> +               value = 3;
> +               break;
> +       case 64:
> +               value = 4;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0022_PCM_CLK_SETUP,
> +               MAX98927_PCM_CLK_SETUP_BSEL_MASK,
> +               value);
> +       return 0;
> +}
> +
> +static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
> +       struct snd_pcm_hw_params *params,
> +       struct snd_soc_dai *dai)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int sampling_rate = 0;
> +       unsigned int chan_sz = 0;
> +
> +       /* pcm mode configuration */
> +       switch (snd_pcm_format_width(params_format(params))) {
> +       case 16:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
> +               break;
> +       case 24:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
> +               break;
> +       case 32:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
> +               break;
> +       default:
> +               dev_err(codec->dev, "format unsupported %d",
> +                       params_format(params));
> +               goto err;
> +       }
> +
> +       max98927->ch_size = snd_pcm_format_width(params_format(params));
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
> +
> +       dev_dbg(codec->dev, "format supported %d",
> +               params_format(params));
> +
> +       /* sampling rate configuration */
> +       switch (params_rate(params)) {
> +       case 8000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_8000;
> +               break;
> +       case 11025:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_11025;
> +               break;
> +       case 12000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_12000;
> +               break;
> +       case 16000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_16000;
> +               break;
> +       case 22050:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_22050;
> +               break;
> +       case 24000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_24000;
> +               break;
> +       case 32000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_32000;
> +               break;
> +       case 44100:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_44100;
> +               break;
> +       case 48000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_48000;
> +               break;
> +       default:
> +               dev_err(codec->dev, "rate %d not supported\n",
> +                       params_rate(params));
> +               goto err;
> +       }
> +       /* set DAI_SR to correct LRCLK frequency */
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0023_PCM_SR_SETUP1,
> +               MAX98927_PCM_SR_SET1_SR_MASK,
> +               sampling_rate);
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0024_PCM_SR_SETUP2,
> +               MAX98927_PCM_SR_SET2_SR_MASK,
> +               sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT);
> +
> +       /* set sampling rate of IV */
> +       if (max98927->interleave_mode &&
> +           sampling_rate > MAX98927_PCM_SR_SET1_SR_16000)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate - 3);
> +       else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate);
> +       return max98927_set_clock(max98927, params);
> +err:
> +       return -EINVAL;
> +}
> +
> +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000
> +
> +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
> +       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
> +
> +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai,
> +       int clk_id, unsigned int freq, int dir)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->sysclk = freq;
> +       return 0;
> +}
> +
> +static const struct snd_soc_dai_ops max98927_dai_ops = {
> +       .set_sysclk = max98927_dai_set_sysclk,
> +       .set_fmt = max98927_dai_set_fmt,
> +       .hw_params = max98927_dai_hw_params,
> +};
> +
> +static int max98927_dac_event(struct snd_soc_dapm_widget *w,
> +       struct snd_kcontrol *kcontrol, int event)
> +{
> +       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       switch (event) {
> +       case SND_SOC_DAPM_POST_PMU:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 1);
> +               /* enable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 1);
> +               break;
> +       case SND_SOC_DAPM_POST_PMD:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 0);
> +               /* disable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, 0);
> +               break;
> +       default:
> +               return 0;
> +       }
> +       return 0;
> +}
> +
> +static const char * const max98927_switch_text[] = {
> +       "Left", "Right", "LeftRight"};
> +
> +static const struct soc_enum dai_sel_enum =
> +       SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
> +               3, max98927_switch_text);
> +
> +static const struct snd_kcontrol_new max98927_dai_controls =
> +       SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
> +
> +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = {
> +       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
> +       SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN,
> +               0, 0, max98927_dac_event,
> +               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
> +       SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
> +               &max98927_dai_controls),
> +       SND_SOC_DAPM_OUTPUT("BE_OUT"),
> +};
> +
> +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0);
> +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0);
> +
> +static bool max98927_readable_register(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B:
> +       case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B:
> +       case MAX98927_R002E_ICC_HIZ_MANUAL_MODE
> +               ... MAX98927_R004E_MEAS_ADC_CH2_READ:
> +       case MAX98927_R0051_BROWNOUT_STATUS
> +               ... MAX98927_R0055_BROWNOUT_LVL_HOLD:
> +       case MAX98927_R005A_BROWNOUT_LVL1_THRESH
> +               ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE:
> +       case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT
> +               ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ:
> +       case MAX98927_R00FF_GLOBAL_SHDN:
> +       case MAX98927_R0100_SOFT_RESET:
> +       case MAX98927_R01FF_REV_ID:
> +               return true;
> +       default:
> +               return false;
> +       }
> +};
> +
> +static bool max98927_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static const char * const max98927_boost_voltage_text[] = {
> +       "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
> +       "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
> +       "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
> +       "9.5V", "9.625V", "9.75V", "9.875V", "10V"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_boost_voltage,
> +               MAX98927_R0040_BOOST_CTRL0, 0,
> +               max98927_boost_voltage_text);
> +
> +static const char * const max98927_current_limit_text[] = {
> +       "1.00A", "1.10A", "1.20A", "1.30A", "1.40A", "1.50A", "1.60A", "1.70A",
> +       "1.80A", "1.90A", "2.00A", "2.10A", "2.20A", "2.30A", "2.40A", "2.50A",
> +       "2.60A", "2.70A", "2.80A", "2.90A", "3.00A", "3.10A", "3.20A", "3.30A",
> +       "3.40A", "3.50A", "3.60A", "3.70A", "3.80A", "3.90A", "4.00A", "4.10A"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_current_limit,
> +               MAX98927_R0042_BOOST_CTRL1, 1,
> +               max98927_current_limit_text);
> +
> +static const struct snd_kcontrol_new max98927_snd_controls[] = {
> +       SOC_SINGLE_TLV("Speaker Volume", MAX98927_R003C_SPK_GAIN,
> +               0, 6, 0,
> +               max98927_spk_tlv),
> +       SOC_SINGLE_TLV("Digital Volume", MAX98927_R0036_AMP_VOL_CTRL,
> +               0, (1<<MAX98927_AMP_VOL_WIDTH)-1, 0,
> +               max98927_digital_tlv),
> +       SOC_SINGLE("Amp DSP Switch", MAX98927_R0052_BROWNOUT_EN,
> +               MAX98927_BROWNOUT_DSP_SHIFT, 1, 0),
> +       SOC_SINGLE("Ramp Switch", MAX98927_R0037_AMP_DSP_CFG,
> +               MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0),
> +       SOC_SINGLE("DRE Switch", MAX98927_R0039_DRE_CTRL,
> +               MAX98927_DRE_EN_SHIFT, 1, 0),
> +       SOC_SINGLE("Volume Location Switch", MAX98927_R0036_AMP_VOL_CTRL,
> +               MAX98927_AMP_VOL_SEL_SHIFT, 1, 0),
> +       SOC_ENUM("Boost Output Voltage", max98927_boost_voltage),
> +       SOC_ENUM("Current Limit", max98927_current_limit),
> +};
> +
> +static const struct snd_soc_dapm_route max98927_audio_map[] = {
> +       {"Amp Enable", NULL, "DAI_OUT"},
> +       {"DAI Sel Mux", "Left", "Amp Enable"},
> +       {"DAI Sel Mux", "Right", "Amp Enable"},
> +       {"DAI Sel Mux", "LeftRight", "Amp Enable"},
> +       {"BE_OUT", NULL, "DAI Sel Mux"},
> +};
> +
> +static struct snd_soc_dai_driver max98927_dai[] = {
> +       {
> +               .name = "max98927-aif1",
> +               .playback = {
> +                       .stream_name = "HiFi Playback",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .capture = {
> +                       .stream_name = "HiFi Capture",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .ops = &max98927_dai_ops,
> +       }
> +};
> +
> +static int max98927_probe(struct snd_soc_codec *codec)
> +{
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->codec = codec;
> +       codec->control_data = max98927->regmap;
> +       codec->cache_bypass = 1;
> +
> +       /* Software Reset */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0100_SOFT_RESET, MAX98927_SOFT_RESET);
> +
> +       /* IV default slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               0x80);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,
> +               0x1);
> +       /* Set inital volume (+13dB) */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0036_AMP_VOL_CTRL,
> +               0x38);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003C_SPK_GAIN,
> +               0x05);
> +       /* Enable DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0037_AMP_DSP_CFG,
> +               0x03);
> +       /* Enable IMON VMON DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003F_MEAS_DSP_CFG,
> +               0xF7);
> +       /* Boost Output Voltage & Current limit */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0040_BOOST_CTRL0,
> +               0x1C);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0042_BOOST_CTRL1,
> +               0x3E);
> +       /* Measurement ADC config */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0043_MEAS_ADC_CFG,
> +               0x04);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0044_MEAS_ADC_BASE_MSB,
> +               0x00);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0045_MEAS_ADC_BASE_LSB,
> +               0x24);
> +       /* Brownout Level */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,
> +               0x06);
> +       /* Envelope Tracking configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,
> +               0x08);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0086_ENV_TRACK_CTRL,
> +               0x01);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,
> +               0x10);
> +
> +       /* voltage, current slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001E_PCM_TX_CH_SRC_A,
> +               (max98927->i_l_slot<<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT|
> +               max98927->v_l_slot)&0xFF);
> +
> +       if (max98927->v_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->v_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->v_l_slot,
> +                       1 << max98927->v_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->v_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->v_l_slot - 8),
> +                       1 << (max98927->v_l_slot - 8));
> +       }
> +
> +       if (max98927->i_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->i_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->i_l_slot,
> +                       1 << max98927->i_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->i_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->i_l_slot - 8),
> +                       1 << (max98927->i_l_slot - 8));
> +       }
> +
> +       /* Set interleave mode */
> +       if (max98927->interleave_mode)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001F_PCM_TX_CH_SRC_B,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK);
> +       return 0;
> +}
> +
> +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = {
> +       .probe = max98927_probe,
> +       .component_driver = {
> +               .controls = max98927_snd_controls,
> +               .num_controls = ARRAY_SIZE(max98927_snd_controls),
> +               .dapm_widgets = max98927_dapm_widgets,
> +               .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets),
> +               .dapm_routes = max98927_audio_map,
> +               .num_dapm_routes = ARRAY_SIZE(max98927_audio_map),
> +       },
> +};
> +
> +static const struct regmap_config max98927_regmap = {
> +       .reg_bits         = 16,
> +       .val_bits         = 8,
> +       .max_register     = MAX98927_R01FF_REV_ID,
> +       .reg_defaults     = max98927_reg,
> +       .num_reg_defaults = ARRAY_SIZE(max98927_reg),
> +       .readable_reg     = max98927_readable_register,
> +       .volatile_reg     = max98927_volatile_reg,
> +       .cache_type       = REGCACHE_RBTREE,
> +};
> +
> +static void max98927_slot_config(struct i2c_client *i2c,
> +       struct max98927_priv *max98927)
> +{
> +       int value;
> +
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "vmon-slot-no", &value))
> +               max98927->v_l_slot = value & 0xF;
> +       else
> +               max98927->v_l_slot = 0;
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "imon-slot-no", &value))
> +               max98927->i_l_slot = value & 0xF;
> +       else
> +               max98927->i_l_slot = 1;
> +}
> +
> +static int max98927_i2c_probe(struct i2c_client *i2c,
> +       const struct i2c_device_id *id)
> +{
> +
> +       int ret = 0, value;
> +       int reg = 0;
> +       struct max98927_priv *max98927 = NULL;
> +
> +       max98927 = devm_kzalloc(&i2c->dev,
> +               sizeof(*max98927), GFP_KERNEL);
> +
> +       if (!max98927) {
> +               ret = -ENOMEM;
> +               return ret;
> +       }
> +       i2c_set_clientdata(i2c, max98927);
> +
> +       /* update interleave mode info */
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "interleave_mode", &value)) {
> +               if (value > 0)
> +                       max98927->interleave_mode = 1;
> +               else
> +                       max98927->interleave_mode = 0;
> +       } else
> +               max98927->interleave_mode = 0;
> +
> +       /* regmap initialization */
> +       max98927->regmap
> +               = devm_regmap_init_i2c(i2c, &max98927_regmap);
> +       if (IS_ERR(max98927->regmap)) {
> +               ret = PTR_ERR(max98927->regmap);
> +               dev_err(&i2c->dev,
> +                       "Failed to allocate regmap: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* Check Revision ID */
> +       ret = regmap_read(max98927->regmap,
> +               MAX98927_R01FF_REV_ID, &reg);
> +       if (ret < 0) {
> +               dev_err(&i2c->dev,
> +                       "Failed to read: 0x%02X\n", MAX98927_R01FF_REV_ID);
> +               return ret;
> +       }
> +       dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n", reg);
> +
> +       /* voltage/current slot configuration */
> +       max98927_slot_config(i2c, max98927);
> +
> +       /* codec registeration */
> +       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927,
> +               max98927_dai, ARRAY_SIZE(max98927_dai));
> +       if (ret < 0)
> +               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static int max98927_i2c_remove(struct i2c_client *client)
> +{
> +       snd_soc_unregister_codec(&client->dev);
> +       return 0;
> +}
> +
> +static const struct i2c_device_id max98927_i2c_id[] = {
> +       { "max98927", 0},
> +       { },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id max98927_of_match[] = {
> +       { .compatible = "maxim,max98927", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, max98927_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id max98927_acpi_match[] = {
> +       { "MX98927", 0 },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(acpi, max98927_acpi_match);
> +#endif
> +
> +static struct i2c_driver max98927_i2c_driver = {
> +       .driver = {
> +               .name = "max98927",
> +               .of_match_table = of_match_ptr(max98927_of_match),
> +               .acpi_match_table = ACPI_PTR(max98927_acpi_match),
> +               .pm = NULL,
> +       },
> +       .probe  = max98927_i2c_probe,
> +       .remove = max98927_i2c_remove,
> +       .id_table = max98927_i2c_id,
> +};
> +
> +module_i2c_driver(max98927_i2c_driver)
> +
> +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver");
> +MODULE_AUTHOR("Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h
> new file mode 100644
> index 000000000000..ece6a608cbe1
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.h
> @@ -0,0 +1,272 @@
> +/*
> + * max98927.h  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright 2013-15 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + */
> +#ifndef _MAX98927_H
> +#define _MAX98927_H
> +
> +/* Register Values */
> +#define MAX98927_R0001_INT_RAW1 0x0001
> +#define MAX98927_R0002_INT_RAW2 0x0002
> +#define MAX98927_R0003_INT_RAW3 0x0003
> +#define MAX98927_R0004_INT_STATE1 0x0004
> +#define MAX98927_R0005_INT_STATE2 0x0005
> +#define MAX98927_R0006_INT_STATE3 0x0006
> +#define MAX98927_R0007_INT_FLAG1 0x0007
> +#define MAX98927_R0008_INT_FLAG2 0x0008
> +#define MAX98927_R0009_INT_FLAG3 0x0009
> +#define MAX98927_R000A_INT_EN1 0x000A
> +#define MAX98927_R000B_INT_EN2 0x000B
> +#define MAX98927_R000C_INT_EN3 0x000C
> +#define MAX98927_R000D_INT_FLAG_CLR1   0x000D
> +#define MAX98927_R000E_INT_FLAG_CLR2   0x000E
> +#define MAX98927_R000F_INT_FLAG_CLR3   0x000F
> +#define MAX98927_R0010_IRQ_CTRL 0x0010
> +#define MAX98927_R0011_CLK_MON 0x0011
> +#define MAX98927_R0012_WDOG_CTRL 0x0012
> +#define MAX98927_R0013_WDOG_RST 0x0013
> +#define MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH 0x0014
> +#define MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH 0x0015
> +#define MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS 0x0016
> +#define MAX98927_R0017_PIN_CFG 0x0017
> +#define MAX98927_R0018_PCM_RX_EN_A 0x0018
> +#define MAX98927_R0019_PCM_RX_EN_B 0x0019
> +#define MAX98927_R001A_PCM_TX_EN_A 0x001A
> +#define MAX98927_R001B_PCM_TX_EN_B 0x001B
> +#define MAX98927_R001C_PCM_TX_HIZ_CTRL_A 0x001C
> +#define MAX98927_R001D_PCM_TX_HIZ_CTRL_B 0x001D
> +#define MAX98927_R001E_PCM_TX_CH_SRC_A 0x001E
> +#define MAX98927_R001F_PCM_TX_CH_SRC_B 0x001F
> +#define MAX98927_R0020_PCM_MODE_CFG 0x0020
> +#define MAX98927_R0021_PCM_MASTER_MODE 0x0021
> +#define MAX98927_R0022_PCM_CLK_SETUP 0x0022
> +#define MAX98927_R0023_PCM_SR_SETUP1 0x0023
> +#define MAX98927_R0024_PCM_SR_SETUP2   0x0024
> +#define MAX98927_R0025_PCM_TO_SPK_MONOMIX_A 0x0025
> +#define MAX98927_R0026_PCM_TO_SPK_MONOMIX_B 0x0026
> +#define MAX98927_R0027_ICC_RX_EN_A 0x0027
> +#define MAX98927_R0028_ICC_RX_EN_B 0x0028
> +#define MAX98927_R002B_ICC_TX_EN_A 0x002B
> +#define MAX98927_R002C_ICC_TX_EN_B 0x002C
> +#define MAX98927_R002E_ICC_HIZ_MANUAL_MODE 0x002E
> +#define MAX98927_R002F_ICC_TX_HIZ_EN_A 0x002F
> +#define MAX98927_R0030_ICC_TX_HIZ_EN_B 0x0030
> +#define MAX98927_R0031_ICC_LNK_EN 0x0031
> +#define MAX98927_R0032_PDM_TX_EN 0x0032
> +#define MAX98927_R0033_PDM_TX_HIZ_CTRL 0x0033
> +#define MAX98927_R0034_PDM_TX_CTRL 0x0034
> +#define MAX98927_R0035_PDM_RX_CTRL 0x0035
> +#define MAX98927_R0036_AMP_VOL_CTRL 0x0036
> +#define MAX98927_R0037_AMP_DSP_CFG 0x0037
> +#define MAX98927_R0038_TONE_GEN_DC_CFG 0x0038
> +#define MAX98927_R0039_DRE_CTRL 0x0039
> +#define MAX98927_R003A_AMP_EN 0x003A
> +#define MAX98927_R003B_SPK_SRC_SEL 0x003B
> +#define MAX98927_R003C_SPK_GAIN 0x003C
> +#define MAX98927_R003D_SSM_CFG 0x003D
> +#define MAX98927_R003E_MEAS_EN 0x003E
> +#define MAX98927_R003F_MEAS_DSP_CFG 0x003F
> +#define MAX98927_R0040_BOOST_CTRL0 0x0040
> +#define MAX98927_R0041_BOOST_CTRL3 0x0041
> +#define MAX98927_R0042_BOOST_CTRL1 0x0042
> +#define MAX98927_R0043_MEAS_ADC_CFG 0x0043
> +#define MAX98927_R0044_MEAS_ADC_BASE_MSB 0x0044
> +#define MAX98927_R0045_MEAS_ADC_BASE_LSB 0x0045
> +#define MAX98927_R0046_ADC_CH0_DIVIDE 0x0046
> +#define MAX98927_R0047_ADC_CH1_DIVIDE 0x0047
> +#define MAX98927_R0048_ADC_CH2_DIVIDE 0x0048
> +#define MAX98927_R0049_ADC_CH0_FILT_CFG 0x0049
> +#define MAX98927_R004A_ADC_CH1_FILT_CFG 0x004A
> +#define MAX98927_R004B_ADC_CH2_FILT_CFG 0x004B
> +#define MAX98927_R004C_MEAS_ADC_CH0_READ 0x004C
> +#define MAX98927_R004D_MEAS_ADC_CH1_READ 0x004D
> +#define MAX98927_R004E_MEAS_ADC_CH2_READ 0x004E
> +#define MAX98927_R0051_BROWNOUT_STATUS 0x0051
> +#define MAX98927_R0052_BROWNOUT_EN 0x0052
> +#define MAX98927_R0053_BROWNOUT_INFINITE_HOLD 0x0053
> +#define MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR 0x0054
> +#define MAX98927_R0055_BROWNOUT_LVL_HOLD 0x0055
> +#define MAX98927_R005A_BROWNOUT_LVL1_THRESH 0x005A
> +#define MAX98927_R005B_BROWNOUT_LVL2_THRESH 0x005B
> +#define MAX98927_R005C_BROWNOUT_LVL3_THRESH 0x005C
> +#define MAX98927_R005D_BROWNOUT_LVL4_THRESH 0x005D
> +#define MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS 0x005E
> +#define MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL 0x005F
> +#define MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL 0x0060
> +#define MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE 0x0061
> +#define MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 0x0072
> +#define MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1 0x0073
> +#define MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2 0x0074
> +#define MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3 0x0075
> +#define MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT 0x0076
> +#define MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1 0x0077
> +#define MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2 0x0078
> +#define MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3 0x0079
> +#define MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT 0x007A
> +#define MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1 0x007B
> +#define MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2 0x007C
> +#define MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3 0x007D
> +#define MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT 0x007E
> +#define MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1 0x007F
> +#define MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2 0x0080
> +#define MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3 0x0081
> +#define MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM 0x0082
> +#define MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY 0x0083
> +#define MAX98927_R0084_ENV_TRACK_REL_RATE 0x0084
> +#define MAX98927_R0085_ENV_TRACK_HOLD_RATE 0x0085
> +#define MAX98927_R0086_ENV_TRACK_CTRL 0x0086
> +#define MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ 0x0087
> +#define MAX98927_R00FF_GLOBAL_SHDN 0x00FF
> +#define MAX98927_R0100_SOFT_RESET 0x0100
> +#define MAX98927_R01FF_REV_ID 0x01FF
> +
> +/* MAX98927_R0018_PCM_RX_EN_A */
> +#define MAX98927_PCM_RX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_RX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_RX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_RX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_RX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_RX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_RX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_RX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001A_PCM_TX_EN_A */
> +#define MAX98927_PCM_TX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_TX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_TX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_TX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_TX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_TX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_TX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_TX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001E_PCM_TX_CH_SRC_A */
> +#define MAX98927_PCM_TX_CH_SRC_A_V_SHIFT (0)
> +#define MAX98927_PCM_TX_CH_SRC_A_I_SHIFT (4)
> +
> +/* MAX98927_R001F_PCM_TX_CH_SRC_B */
> +#define MAX98927_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 5)
> +
> +/* MAX98927_R0020_PCM_MODE_CFG */
> +#define MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3)
> +#define MAX98927_PCM_FORMAT_I2S (0x0 << 0)
> +#define MAX98927_PCM_FORMAT_LJ (0x1 << 0)
> +
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
> +
> +/* MAX98927_R0021_PCM_MASTER_MODE */
> +#define MAX98927_PCM_MASTER_MODE_MASK (0x3 << 0)
> +#define MAX98927_PCM_MASTER_MODE_SLAVE (0x0 << 0)
> +#define MAX98927_PCM_MASTER_MODE_MASTER (0x3 << 0)
> +
> +#define MAX98927_PCM_MASTER_MODE_MCLK_MASK (0xF << 2)
> +#define MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2)
> +
> +/* MAX98927_R0022_PCM_CLK_SETUP */
> +#define MAX98927_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
> +
> +/* MAX98927_R0023_PCM_SR_SETUP1 */
> +#define MAX98927_PCM_SR_SET1_SR_MASK (0xF << 0)
> +
> +#define MAX98927_PCM_SR_SET1_SR_8000 (0x0 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_11025 (0x1 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_12000 (0x2 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_16000 (0x3 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_22050 (0x4 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_24000 (0x5 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_32000 (0x6 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_44100 (0x7 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_48000 (0x8 << 0)
> +
> +/* MAX98927_R0024_PCM_SR_SETUP2 */
> +#define MAX98927_PCM_SR_SET2_SR_MASK (0xF << 4)
> +#define MAX98927_PCM_SR_SET2_SR_SHIFT (4)
> +#define MAX98927_PCM_SR_SET2_IVADC_SR_MASK (0xf << 0)
> +
> +/* MAX98927_R0025_PCM_TO_SPK_MONOMIX_A */
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
> +
> +/* MAX98927_R0035_PDM_RX_CTRL */
> +#define MAX98927_PDM_RX_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R0036_AMP_VOL_CTRL */
> +#define MAX98927_AMP_VOL_SEL (0x1 << 7)
> +#define MAX98927_AMP_VOL_SEL_WIDTH (1)
> +#define MAX98927_AMP_VOL_SEL_SHIFT (7)
> +#define MAX98927_AMP_VOL_MASK (0x7f << 0)
> +#define MAX98927_AMP_VOL_WIDTH (7)
> +#define MAX98927_AMP_VOL_SHIFT (0)
> +
> +/* MAX98927_R0037_AMP_DSP_CFG */
> +#define MAX98927_AMP_DSP_CFG_DCBLK_EN (0x1 << 0)
> +#define MAX98927_AMP_DSP_CFG_DITH_EN (0x1 << 1)
> +#define MAX98927_AMP_DSP_CFG_RMP_BYPASS (0x1 << 4)
> +#define MAX98927_AMP_DSP_CFG_DAC_INV (0x1 << 5)
> +#define MAX98927_AMP_DSP_CFG_RMP_SHIFT (4)
> +
> +/* MAX98927_R0039_DRE_CTRL */
> +#define MAX98927_DRE_CTRL_DRE_EN       (0x1 << 0)
> +#define MAX98927_DRE_EN_SHIFT 0x1
> +
> +/* MAX98927_R003A_AMP_EN */
> +#define MAX98927_AMP_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R003B_SPK_SRC_SEL */
> +#define MAX98927_SPK_SRC_MASK (0x3 << 0)
> +
> +/* MAX98927_R003C_SPK_GAIN */
> +#define MAX98927_SPK_PCM_GAIN_MASK (0x7 << 0)
> +#define MAX98927_SPK_PDM_GAIN_MASK (0x7 << 4)
> +#define MAX98927_SPK_GAIN_WIDTH (3)
> +
> +/* MAX98927_R003E_MEAS_EN */
> +#define MAX98927_MEAS_V_EN (0x1 << 0)
> +#define MAX98927_MEAS_I_EN (0x1 << 1)
> +
> +/* MAX98927_R0040_BOOST_CTRL0 */
> +#define MAX98927_BOOST_CTRL0_VOUT_MASK (0x1f << 0)
> +#define MAX98927_BOOST_CTRL0_PVDD_MASK (0x1 << 7)
> +#define MAX98927_BOOST_CTRL0_PVDD_EN_SHIFT (7)
> +
> +/* MAX98927_R0052_BROWNOUT_EN */
> +#define MAX98927_BROWNOUT_BDE_EN (0x1 << 0)
> +#define MAX98927_BROWNOUT_AMP_EN (0x1 << 1)
> +#define MAX98927_BROWNOUT_DSP_EN (0x1 << 2)
> +#define MAX98927_BROWNOUT_DSP_SHIFT (2)
> +
> +/* MAX98927_R0100_SOFT_RESET */
> +#define MAX98927_SOFT_RESET (0x1 << 0)
> +
> +/* MAX98927_R00FF_GLOBAL_SHDN */
> +#define MAX98927_GLOBAL_EN_MASK (0x1 << 0)
> +
> +struct max98927_priv {
> +       struct regmap *regmap;
> +       struct snd_soc_codec *codec;
> +       struct max98927_pdata *pdata;
> +       unsigned int spk_gain;
> +       unsigned int sysclk;
> +       unsigned int v_l_slot;
> +       unsigned int i_l_slot;
> +       bool interleave_mode;
> +       unsigned int ch_size;
> +       unsigned int rate;
> +       unsigned int iface;
> +       unsigned int master;
> +       unsigned int digital_gain;
> +};
> +#endif
> --
> 2.11.0
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 15/18] dt-bindings: sound: Add bindings for Cirrus Logic Madera codecs
From: Richard Fitzgerald @ 2017-04-25 16:27 UTC (permalink / raw)
  To: Mark Brown
  Cc: gnurou, alsa-devel, jason, devicetree, linus.walleij, patches,
	linux-kernel, linux-gpio, robh+dt, tglx, lee.jones
In-Reply-To: <20170425155257.s6m4wgrzxxsxcggo@sirena.org.uk>

On Tue, 2017-04-25 at 16:52 +0100, Mark Brown wrote:
> On Mon, Apr 24, 2017 at 05:08:41PM +0100, Richard Fitzgerald wrote:
> > The Cirrus Logic Madera codecs are a family of related codecs with
> > extensive digital and analogue I/O, digital mixing and routing,
> > signal processing and programmable DSPs.
> 
> Please submit patches using subject lines reflecting the style for the
> subsystem.  This makes it easier for people to identify relevant
> patches.  Look at what existing commits in the area you're changing are
> doing and make sure your subject lines visually resemble what they're
> doing.
> 
> > +Required properties:
> > +  - compatible : One of the following chip-specific strings:
> > +        "cirrus,cs47l35-codec"
> > +        "cirrus,cs47l85-codec"
> > +        "cirrus,cs47l90-codec"
> 
> You shouldn't have compatible strings for subfunctions of a MFD unless
> these represent meaningful reusable IPs that can exist separately from
> the parent chip, that's clearly not the case here.  All you're doing
> here is encoding Linux internal abstractions which aren't OS neutral and
> might change in future (for example clocking might move more into the
> clock API).

While that's nice, the of_node doesn't get populated if there isn't a
compatible string. And people don't like workarounds for the missing
of_node.

^ permalink raw reply

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Mark Brown @ 2017-04-25 16:28 UTC (permalink / raw)
  To: Ryan Lee
  Cc: Liam Girdwood, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
	Kuninori Morimoto, Arnd Bergmann,
	ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	lars-Qo5EllUWu/uELgA04lAiVw, bardliao-Rasf1IRRPZFBDgjK7y7TUQ,
	nh6z-fFIq/eER6g8, KCHSU0-KrzQf0k3Iz9BDgjK7y7TUQ, Axel Lin,
	romain.perier-ZGY8ohtN/8qB+jHODAdFcQ, Srinivas Kandagatla,
	oder_chiou-Rasf1IRRPZFBDgjK7y7TUQ,
	Paul.Handrigan-jGc1dHjMKG3QT0dZR+AlfA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dylan Reid
In-Reply-To: <CAN4-oj=suA8Bx_QLGOvGkjr=CgUwhPibNRk31Y_JaBydZX6USg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 544 bytes --]

On Tue, Apr 25, 2017 at 09:24:34AM -0700, Ryan Lee wrote:
> I was not able to see any activities about MAX98927 driver after previous mail.
> Is there anything wrong with this driver?

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.

I'm not sure what communication you're expecting...  if nobody is
complaining about your driver that's probably good?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes
From: Philipp Zabel @ 2017-04-25 16:32 UTC (permalink / raw)
  To: Peter Rosin
  Cc: Jonathan Cameron, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Greg Kroah-Hartman, Wolfram Sang, Rob Herring, Mark Rutland,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Jonathan Corbet, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Andrew Morton, Colin Ian King,
	Paul Gortmaker, kernel-bIcnvbaLZ9MEGnE8C9+IrQ
In-Reply-To: <e53bbf82-793f-b22f-2e9b-4bd377446351-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On Tue, 2017-04-25 at 16:55 +0200, Peter Rosin wrote:
> On 2017-04-25 16:16, Peter Rosin wrote:
> > On 2017-04-24 16:59, Philipp Zabel wrote:
> >> On Mon, 2017-04-24 at 16:36 +0200, Peter Rosin wrote:
> >> [...]
> >>>> How about an atomic use_count on the mux_control, a bool shared that is
> >>>> only set by the first consumer, and controls whether selecting locks?
> >>>
> >>> That has the drawback that it is hard to restore the mux-control in a safe
> >>> way so that exclusive consumers are allowed after the last shared consumer
> >>> puts the mux away.
> >>
> >> True.
> >>
> >>> Agreed, it's a corner case, but I had this very similar
> >>> patch going through the compiler when I got this mail. Does it work as well
> >>> as what you suggested?
> >>
> >> Yes, this patch works just as well.
> > 
> > Right, as expected :-) However, I don't like it much. It divides the mux
> > consumers into two camps in a way that makes it difficult to select which
> > camp a consumer should be in.
> > 
> > E.g. consider the iio-mux. The current implementation only supports quick
> > accesses that fit the mux_control_get_shared case. But if that mux in the
> > future needs to grow continuous buffered accesses, I think there will be
> > pressure to switch it over to the exclusive mode. Because that is a lot
> > closer to what you are doing with the video-mux. And then what? It will be
> > impossible to predict if the end user is going to use buffered accesses or
> > not...
> > 
> > So, I think the best approach is to skip the distinction between shared
> > and exclusive consumers and instead implement the locking with an ordinary
> > semaphore (instead of the old rwsem or the current mutex). Semaphores don't
> > have the property that the same task should down/up them (mutexes require
> > that for lock/unlock, and is also the reason for the lockdep complaint) and
> > thus fits better for long-time use such as yours or the above iio-mux with
> > buffered accesses. It should also hopefully be cheaper that an rwsem, and
> > not have any downgrade_write calls thus possibly keeping Greg sufficiently
> > happy...

No idea whether this will placate Greg, but it does work for the
video-mux case.
The documentation for mux_control_(try_)select should mention that these
calls will hold the mux lock until deselect is called, and the
documentation for mux_control_select should probably mention that it
will block until the lock is released.

> > Sure, consumers can still dig themselves into a hole by not calling deselect
> > as they should, but at least I think it can be made to work w/o dividing the
> > consumers...
> 
> Like this (only compile-tested). Philipp, it should work the same as with
> the rwsem in v13 and earlier. At least for your case...

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v8 1/3] backlight arcxcnn add arc to vendor prefix
From: Jingoo Han @ 2017-04-25 16:36 UTC (permalink / raw)
  To: 'Olimpiu Dejeu', 'Rob Herring'
  Cc: 'Lee Jones', linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, 'Brian Dodge',
	'Joe Perches', 'Matthew D'Asaro',
	'Daniel Thompson'
In-Reply-To: <2aac01d2bd24$17449a90$45cdcfb0$@arcticsand.com>

On Monday, April 24, 2017 1:56 PM, Olimpiu Dejeu wrote:
> 
> On Mon, April 24, 2017 11:10 AM, Rob Herring < robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> 
> > On Wed, Mar 15, 2017 at 2:45 PM, Olimpiu Dejeu <olimpiu-eV7fy4qpoLhpLGFMi4vTTA@public.gmane.org>
> wrote:
> >> backlight: Add arc to vendor prefixes
> >> Signed-off-by: Olimpiu Dejeu <olimpiu-eV7fy4qpoLhpLGFMi4vTTA@public.gmane.org>
> >> ---
> >> v8:
> >> - Version to match other patches in set
> >>
> >>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> b/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> index 16d3b5e..6f33a4b 100644
> >> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> @@ -28,6 +28,7 @@ andestech     Andes Technology Corporation
> >>  apm    Applied Micro Circuits Corporation (APM)
> >>  aptina Aptina Imaging
> >>  arasan Arasan Chip Systems
> >> +arc    Arctic Sand
> 
> >arc is also a cpu arch. While not a vendor, it could be confusing. How
> about "arctic" >instead?
> 
> Rob, will do, i.e. I will change it to "arctic"

Hi Olimpiu,

Oh, "arc" and "arctic" is totally different.
In my opinion, one of the purposes of DT is to describe hardware stuffs.
So, please use more detailed words.

> 
> >BTW, some reason your patches are not going to the DT list.
> 
> 
> I'm emailing to devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, I think this is the correct
> list. Please advise.

DT is some kind of ABI. It means that changing DT names such as property names
is not easy, after DT patches were merged. So, if someone want to add new DT stuff
into the vanilla kernel, that patch should be reviewed more thoroughly
than normal patches about driver stuffs.

Thanks,
Jingoo Han

> 
> 
> >Rob
> Olimpiu
> 


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 2/2] of: Add unit tests for applying overlays
From: Rob Herring @ 2017-04-25 16:44 UTC (permalink / raw)
  To: Frank Rowand
  Cc: Stephen Boyd, Michal Marek, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Linux Kbuild mailing list
In-Reply-To: <1493075119-32026-3-git-send-email-frowand.list@gmail.com>

On Mon, Apr 24, 2017 at 6:05 PM,  <frowand.list@gmail.com> wrote:
> From: Frank Rowand <frank.rowand@sony.com>
>
> Existing overlay unit tests examine individual pieces of the overlay
> code.  The new tests target the entire process of applying an overlay.

Just a few nits.

> Signed-off-by: Frank Rowand <frank.rowand@sony.com>

[...]

> diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
> index 18bbb4517e25..cc76b3b81eab 100644
> --- a/drivers/of/of_private.h
> +++ b/drivers/of/of_private.h
> @@ -55,6 +55,17 @@ static inline int of_property_notify(int action, struct device_node *np,
>  }
>  #endif /* CONFIG_OF_DYNAMIC */
>
> +#ifdef CONFIG_OF_UNITTEST
> +extern void __init unittest_unflatten_overlay_base(void);
> +extern void *__unflatten_device_tree(const void *blob,

This can and should be outside the ifdef.

> +                             struct device_node *dad,
> +                             struct device_node **mynodes,
> +                             void *(*dt_alloc)(u64 size, u64 align),
> +                             bool detached);
> +#else
> +static inline void unittest_unflatten_overlay_base(void) {};
> +#endif
> +
>  /**
>   * General utilities for working with live trees.
>   *

[...]

> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
> index 62db55b97c10..884f6c1f8ae9 100644
> --- a/drivers/of/unittest.c
> +++ b/drivers/of/unittest.c
> @@ -8,6 +8,7 @@
>  #include <linux/err.h>
>  #include <linux/errno.h>
>  #include <linux/hashtable.h>
> +#include <linux/libfdt.h>
>  #include <linux/of.h>
>  #include <linux/of_fdt.h>
>  #include <linux/of_irq.h>
> @@ -1925,6 +1926,320 @@ static void __init of_unittest_overlay(void)
>  static inline void __init of_unittest_overlay(void) { }
>  #endif
>
> +#ifdef CONFIG_OF_OVERLAY

This can move down to...

> +
> +/*
> + * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
> + * in scripts/Makefile.lib
> + */
> +
> +#define OVERLAY_INFO_EXTERN(name) \
> +       extern uint8_t __dtb_##name##_begin[]; \
> +       extern uint8_t __dtb_##name##_end[]
> +
> +#define OVERLAY_INFO(name, expected) \
> +{      .dtb_begin       = __dtb_##name##_begin, \
> +       .dtb_end         = __dtb_##name##_end, \
> +       .expected_result = expected, \
> +}
> +
> +struct overlay_info {
> +       uint8_t            *dtb_begin;
> +       uint8_t            *dtb_end;
> +       void               *data;
> +       struct device_node *np_overlay;
> +       int                expected_result;
> +       int                overlay_id;
> +};
> +
> +OVERLAY_INFO_EXTERN(overlay_base);
> +OVERLAY_INFO_EXTERN(overlay);
> +OVERLAY_INFO_EXTERN(overlay_bad_phandle);

...here. Maybe we want to move all this to a separate file instead.

> +
> +/* order of entries is hard-coded into users of overlays[] */
> +struct overlay_info overlays[] = {

static?

> +       OVERLAY_INFO(overlay_base, -9999),
> +       OVERLAY_INFO(overlay, 0),
> +       OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
> +       {}
> +};

[...]

> @@ -1962,6 +2277,9 @@ static int __init of_unittest(void)
>         /* Double check linkage after removing testcase data */
>         of_unittest_check_tree_linkage();
>
> +

Extra blank line.

> +       of_unittest_overlay_high_level();
> +
>         pr_info("end of unittest - %i passed, %i failed\n",
>                 unittest_results.passed, unittest_results.failed);
>
> --
> Frank Rowand <frank.rowand@sony.com>
>

^ permalink raw reply

* Re: [PATCH] ARM: dts: Add devicetree for the Raspberry Pi 3, for arm32 (v5)
From: Eric Anholt @ 2017-04-25 16:45 UTC (permalink / raw)
  To: Stefan Wahren, Lee Jones, Florian Fainelli, Olof Johansson,
	Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Gerd Hoffmann,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <68d88bf7-1f47-4056-3b70-7b97d9a02953-eS4NqCHxEME@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]

Stefan Wahren <stefan.wahren-eS4NqCHxEME@public.gmane.org> writes:

> Am 24.04.2017 um 22:00 schrieb Eric Anholt:
>> Raspbian and Fedora have decided to support the Pi3 in 32-bit mode for
>> now, so it's useful to be able to test that mode on an upstream
>> kernel.  It's also been useful for me to use the same board for 32-bit
>> and 64-bit development.
>>
>> Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> ---
>>  arch/arm/boot/dts/Makefile            | 1 +
>>  arch/arm/boot/dts/bcm2837-rpi-3.b.dts | 1 +
>>  2 files changed, 2 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 011808490fed..eded842d9978 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
>>  	bcm2835-rpi-b-plus.dtb \
>>  	bcm2835-rpi-a-plus.dtb \
>>  	bcm2836-rpi-2-b.dtb \
>> +	bcm2837-rpi-3-b.dtb \
>>  	bcm2835-rpi-zero.dtb
>>  dtb-$(CONFIG_ARCH_BCM_5301X) += \
>>  	bcm4708-asus-rt-ac56u.dtb \
>> diff --git a/arch/arm/boot/dts/bcm2837-rpi-3.b.dts b/arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>> new file mode 100644
>> index 000000000000..8c8aa4d1e9b3
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>> @@ -0,0 +1 @@
>> +#include "arm64/broadcom/bcm2837-rpi-3.b.dts"
>
> Looks like a typo in the dts filename and in the include ( dot instead
> of dash ).

Sorry about that, everyone.  I remember doing builds of the patch, but
maybe things succeeded because there was already a .dtb present in my
tree or something.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply

* [PATCH] ARM: dts: Add devicetree for the Raspberry Pi 3, for arm32 (v6)
From: Eric Anholt @ 2017-04-25 16:45 UTC (permalink / raw)
  To: Lee Jones, Florian Fainelli, Olof Johansson, Rob Herring,
	Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Stefan Wahren,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Gerd Hoffmann,
	Eric Anholt

Raspbian and Fedora have decided to support the Pi3 in 32-bit mode for
now, so it's useful to be able to test that mode on an upstream
kernel.  It's also been useful for me to use the same board for 32-bit
and 64-bit development.

Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
---
 arch/arm/boot/dts/Makefile            | 1 +
 arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3-b.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 011808490fed..eded842d9978 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
 	bcm2835-rpi-b-plus.dtb \
 	bcm2835-rpi-a-plus.dtb \
 	bcm2836-rpi-2-b.dtb \
+	bcm2837-rpi-3-b.dtb \
 	bcm2835-rpi-zero.dtb
 dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4708-asus-rt-ac56u.dtb \
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
new file mode 100644
index 000000000000..c72a27d908b6
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
@@ -0,0 +1 @@
+#include "arm64/broadcom/bcm2837-rpi-3-b.dts"
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Ryan Lee @ 2017-04-25 16:51 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, alsa-devel, Kuninori Morimoto, Liam Girdwood, tiwai,
	Srinivas Kandagatla, romain.perier, bardliao, lars, Axel Lin,
	Paul.Handrigan, devicetree, Arnd Bergmann, nh6z, robh+dt, ckeepax,
	Dylan Reid, oder_chiou, Ryan Lee, KCHSU0, linux-kernel
In-Reply-To: <E1cwCZ1-0001o4-Q5@debutante>

'

On Thu, Apr 6, 2017 at 11:55 AM, Mark Brown <broonie@kernel.org> wrote:
> The patch
>
>    ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> has been applied to the asoc tree at
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
>
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.
>
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
>
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
>
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.
>
> Thanks,
> Mark

I have tried to check MAX98927 driver on linux-next tree and
'git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git' but
have failed.
So I wanted to check the current status of MAX98927 driver.
I'm sorry for top-posting.

>
> From 7c0c2000716e64151b3c0c62026c18f31537ebe9 Mon Sep 17 00:00:00 2001
> From: Ryan Lee <ryans.lee@maximintegrated.com>
> Date: Tue, 4 Apr 2017 02:23:08 +0900
> Subject: [PATCH] ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> Signed-off-by: Ryan Lee <ryans.lee@maximintegrated.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  .../devicetree/bindings/sound/max98925.txt         |  22 -
>  .../devicetree/bindings/sound/max98926.txt         |  32 -
>  .../devicetree/bindings/sound/max9892x.txt         |  41 +
>  sound/soc/codecs/Kconfig                           |   5 +
>  sound/soc/codecs/Makefile                          |   2 +
>  sound/soc/codecs/max98927.c                        | 841 +++++++++++++++++++++
>  sound/soc/codecs/max98927.h                        | 272 +++++++
>  7 files changed, 1161 insertions(+), 54 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98925.txt
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98926.txt
>  create mode 100644 Documentation/devicetree/bindings/sound/max9892x.txt
>  create mode 100644 sound/soc/codecs/max98927.c
>  create mode 100644 sound/soc/codecs/max98927.h
>
> diff --git a/Documentation/devicetree/bindings/sound/max98925.txt b/Documentation/devicetree/bindings/sound/max98925.txt
> deleted file mode 100644
> index 27be63e2aa0d..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98925.txt
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -max98925 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98925"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98925@1a {
> -       compatible = "maxim,max98925";
> -       vmon-slot-no = <0>;
> -       imon-slot-no = <2>;
> -       reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt
> deleted file mode 100644
> index 0b7f4e4d5f9a..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98926.txt
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -max98926 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98926"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -                   or in inteleave mode this will be used as
> -                   interleave slot.
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - interleave-mode : When using two MAX98926 in a system it is
> -                      possible to create ADC data that that will
> -                      overflow the frame size. Digital Audio Interleave
> -                      mode provides a means to output VMON and IMON data
> -                      from two devices on a single DOUT line when running
> -                      smaller frames sizes such as 32 BCLKS per LRCLK or
> -                      48 BCLKS per LRCLK.
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98926@1a {
> -   compatible = "maxim,max98926";
> -   vmon-slot-no = <0>;
> -   imon-slot-no = <2>;
> -   reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max9892x.txt b/Documentation/devicetree/bindings/sound/max9892x.txt
> new file mode 100644
> index 000000000000..f6171591ddc6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/max9892x.txt
> @@ -0,0 +1,41 @@
> +Maxim Integrated MAX98925/MAX98926/MAX98927 Speaker Amplifier
> +
> +This device supports I2C.
> +
> +Required properties:
> +
> +  - compatible : should be one of the following
> +    - "maxim,max98925"
> +    - "maxim,max98926"
> +    - "maxim,max98927"
> +
> +  - vmon-slot-no : slot number used to send voltage information
> +                   or in inteleave mode this will be used as
> +                   interleave slot.
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - imon-slot-no : slot number used to send current information
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - interleave-mode : When using two MAX9892X in a system it is
> +                   possible to create ADC data that that will
> +                   overflow the frame size. Digital Audio Interleave
> +                   mode provides a means to output VMON and IMON data
> +                   from two devices on a single DOUT line when running
> +                   smaller frames sizes such as 32 BCLKS per LRCLK or
> +                   48 BCLKS per LRCLK.
> +                   Range : 0 (off), 1 (on),  Default : 0
> +
> +  - reg : the I2C address of the device for I2C
> +
> +Example:
> +
> +codec: max98927@3a {
> +   compatible = "maxim,max98927";
> +   vmon-slot-no = <0>;
> +   imon-slot-no = <1>;
> +   interleave-mode = <0>;
> +   reg = <0x3a>;
> +};
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 9e1718a8cb1c..65e31ab88280 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -89,6 +89,7 @@ config SND_SOC_ALL_CODECS
>         select SND_SOC_MAX9867 if I2C
>         select SND_SOC_MAX98925 if I2C
>         select SND_SOC_MAX98926 if I2C
> +       select SND_SOC_MAX98927 if I2C
>         select SND_SOC_MAX9850 if I2C
>         select SND_SOC_MAX9860 if I2C
>         select SND_SOC_MAX9768 if I2C
> @@ -585,6 +586,10 @@ config SND_SOC_MAX98925
>  config SND_SOC_MAX98926
>         tristate
>
> +config SND_SOC_MAX98927
> +       tristate "Maxim Integrated MAX98927 Speaker Amplifier"
> +       depends on I2C
> +
>  config SND_SOC_MAX9850
>         tristate
>
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 7e1dad79610b..64656c43200c 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -84,6 +84,7 @@ snd-soc-max98371-objs := max98371.o
>  snd-soc-max9867-objs := max9867.o
>  snd-soc-max98925-objs := max98925.o
>  snd-soc-max98926-objs := max98926.o
> +snd-soc-max98927-objs := max98927.o
>  snd-soc-max9850-objs := max9850.o
>  snd-soc-max9860-objs := max9860.o
>  snd-soc-mc13783-objs := mc13783.o
> @@ -312,6 +313,7 @@ obj-$(CONFIG_SND_SOC_MAX98357A)     += snd-soc-max98357a.o
>  obj-$(CONFIG_SND_SOC_MAX9867)  += snd-soc-max9867.o
>  obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
>  obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
> +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
>  obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
>  obj-$(CONFIG_SND_SOC_MAX9860)  += snd-soc-max9860.o
>  obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
> diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c
> new file mode 100644
> index 000000000000..b5ee29499e16
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.c
> @@ -0,0 +1,841 @@
> +/*
> + * max98927.c  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright (C) 2016 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee@maximintegrated.com>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <sound/tlv.h>
> +#include "max98927.h"
> +
> +static struct reg_default max98927_reg[] = {
> +       {MAX98927_R0001_INT_RAW1,  0x00},
> +       {MAX98927_R0002_INT_RAW2,  0x00},
> +       {MAX98927_R0003_INT_RAW3,  0x00},
> +       {MAX98927_R0004_INT_STATE1,  0x00},
> +       {MAX98927_R0005_INT_STATE2,  0x00},
> +       {MAX98927_R0006_INT_STATE3,  0x00},
> +       {MAX98927_R0007_INT_FLAG1,  0x00},
> +       {MAX98927_R0008_INT_FLAG2,  0x00},
> +       {MAX98927_R0009_INT_FLAG3,  0x00},
> +       {MAX98927_R000A_INT_EN1,  0x00},
> +       {MAX98927_R000B_INT_EN2,  0x00},
> +       {MAX98927_R000C_INT_EN3,  0x00},
> +       {MAX98927_R000D_INT_FLAG_CLR1,  0x00},
> +       {MAX98927_R000E_INT_FLAG_CLR2,  0x00},
> +       {MAX98927_R000F_INT_FLAG_CLR3,  0x00},
> +       {MAX98927_R0010_IRQ_CTRL,  0x00},
> +       {MAX98927_R0011_CLK_MON,  0x00},
> +       {MAX98927_R0012_WDOG_CTRL,  0x00},
> +       {MAX98927_R0013_WDOG_RST,  0x00},
> +       {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH,  0x00},
> +       {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH,  0x00},
> +       {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS,  0x00},
> +       {MAX98927_R0017_PIN_CFG,  0x55},
> +       {MAX98927_R0018_PCM_RX_EN_A,  0x00},
> +       {MAX98927_R0019_PCM_RX_EN_B,  0x00},
> +       {MAX98927_R001A_PCM_TX_EN_A,  0x00},
> +       {MAX98927_R001B_PCM_TX_EN_B,  0x00},
> +       {MAX98927_R001C_PCM_TX_HIZ_CTRL_A,  0x00},
> +       {MAX98927_R001D_PCM_TX_HIZ_CTRL_B,  0x00},
> +       {MAX98927_R001E_PCM_TX_CH_SRC_A,  0x00},
> +       {MAX98927_R001F_PCM_TX_CH_SRC_B,  0x00},
> +       {MAX98927_R0020_PCM_MODE_CFG,  0x40},
> +       {MAX98927_R0021_PCM_MASTER_MODE,  0x00},
> +       {MAX98927_R0022_PCM_CLK_SETUP,  0x22},
> +       {MAX98927_R0023_PCM_SR_SETUP1,  0x00},
> +       {MAX98927_R0024_PCM_SR_SETUP2,  0x00},
> +       {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,  0x00},
> +       {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,  0x00},
> +       {MAX98927_R0027_ICC_RX_EN_A,  0x00},
> +       {MAX98927_R0028_ICC_RX_EN_B,  0x00},
> +       {MAX98927_R002B_ICC_TX_EN_A,  0x00},
> +       {MAX98927_R002C_ICC_TX_EN_B,  0x00},
> +       {MAX98927_R002E_ICC_HIZ_MANUAL_MODE,  0x00},
> +       {MAX98927_R002F_ICC_TX_HIZ_EN_A,  0x00},
> +       {MAX98927_R0030_ICC_TX_HIZ_EN_B,  0x00},
> +       {MAX98927_R0031_ICC_LNK_EN,  0x00},
> +       {MAX98927_R0032_PDM_TX_EN,  0x00},
> +       {MAX98927_R0033_PDM_TX_HIZ_CTRL,  0x00},
> +       {MAX98927_R0034_PDM_TX_CTRL,  0x00},
> +       {MAX98927_R0035_PDM_RX_CTRL,  0x00},
> +       {MAX98927_R0036_AMP_VOL_CTRL,  0x00},
> +       {MAX98927_R0037_AMP_DSP_CFG,  0x02},
> +       {MAX98927_R0038_TONE_GEN_DC_CFG,  0x00},
> +       {MAX98927_R0039_DRE_CTRL,  0x01},
> +       {MAX98927_R003A_AMP_EN,  0x00},
> +       {MAX98927_R003B_SPK_SRC_SEL,  0x00},
> +       {MAX98927_R003C_SPK_GAIN,  0x00},
> +       {MAX98927_R003D_SSM_CFG,  0x01},
> +       {MAX98927_R003E_MEAS_EN,  0x00},
> +       {MAX98927_R003F_MEAS_DSP_CFG,  0x04},
> +       {MAX98927_R0040_BOOST_CTRL0,  0x00},
> +       {MAX98927_R0041_BOOST_CTRL3,  0x00},
> +       {MAX98927_R0042_BOOST_CTRL1,  0x00},
> +       {MAX98927_R0043_MEAS_ADC_CFG,  0x00},
> +       {MAX98927_R0044_MEAS_ADC_BASE_MSB,  0x00},
> +       {MAX98927_R0045_MEAS_ADC_BASE_LSB,  0x00},
> +       {MAX98927_R0046_ADC_CH0_DIVIDE,  0x00},
> +       {MAX98927_R0047_ADC_CH1_DIVIDE,  0x00},
> +       {MAX98927_R0048_ADC_CH2_DIVIDE,  0x00},
> +       {MAX98927_R0049_ADC_CH0_FILT_CFG,  0x00},
> +       {MAX98927_R004A_ADC_CH1_FILT_CFG,  0x00},
> +       {MAX98927_R004B_ADC_CH2_FILT_CFG,  0x00},
> +       {MAX98927_R004C_MEAS_ADC_CH0_READ,  0x00},
> +       {MAX98927_R004D_MEAS_ADC_CH1_READ,  0x00},
> +       {MAX98927_R004E_MEAS_ADC_CH2_READ,  0x00},
> +       {MAX98927_R0051_BROWNOUT_STATUS,  0x00},
> +       {MAX98927_R0052_BROWNOUT_EN,  0x00},
> +       {MAX98927_R0053_BROWNOUT_INFINITE_HOLD,  0x00},
> +       {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR,  0x00},
> +       {MAX98927_R0055_BROWNOUT_LVL_HOLD,  0x00},
> +       {MAX98927_R005A_BROWNOUT_LVL1_THRESH,  0x00},
> +       {MAX98927_R005B_BROWNOUT_LVL2_THRESH,  0x00},
> +       {MAX98927_R005C_BROWNOUT_LVL3_THRESH,  0x00},
> +       {MAX98927_R005D_BROWNOUT_LVL4_THRESH,  0x00},
> +       {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS,  0x00},
> +       {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL,  0x00},
> +       {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL,  0x00},
> +       {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE,  0x00},
> +       {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT,  0x00},
> +       {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT,  0x00},
> +       {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT,  0x00},
> +       {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1,  0x00},
> +       {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2,  0x00},
> +       {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT,  0x00},
> +       {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,  0x00},
> +       {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY,  0x00},
> +       {MAX98927_R0084_ENV_TRACK_REL_RATE,  0x00},
> +       {MAX98927_R0085_ENV_TRACK_HOLD_RATE,  0x00},
> +       {MAX98927_R0086_ENV_TRACK_CTRL,  0x00},
> +       {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,  0x00},
> +       {MAX98927_R00FF_GLOBAL_SHDN,  0x00},
> +       {MAX98927_R0100_SOFT_RESET,  0x00},
> +       {MAX98927_R01FF_REV_ID,  0x40},
> +};
> +
> +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
> +{
> +       struct snd_soc_codec *codec = codec_dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int mode = 0;
> +       unsigned int format = 0;
> +       unsigned int invert = 0;
> +
> +       dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
> +
> +       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +       case SND_SOC_DAIFMT_CBS_CFS:
> +               mode = MAX98927_PCM_MASTER_MODE_SLAVE;
> +               break;
> +       case SND_SOC_DAIFMT_CBM_CFM:
> +               max98927->master = true;
> +               mode = MAX98927_PCM_MASTER_MODE_MASTER;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI clock mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0021_PCM_MASTER_MODE,
> +               MAX98927_PCM_MASTER_MODE_MASK,
> +               mode);
> +
> +       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +       case SND_SOC_DAIFMT_NB_NF:
> +               break;
> +       case SND_SOC_DAIFMT_IB_NF:
> +               invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI invert mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE,
> +               invert);
> +
> +       /* interface format */
> +       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +       case SND_SOC_DAIFMT_I2S:
> +               max98927->iface |= SND_SOC_DAIFMT_I2S;
> +               format = MAX98927_PCM_FORMAT_I2S;
> +               break;
> +       case SND_SOC_DAIFMT_LEFT_J:
> +               max98927->iface |= SND_SOC_DAIFMT_LEFT_J;
> +               format = MAX98927_PCM_FORMAT_LJ;
> +               break;
> +       case SND_SOC_DAIFMT_PDM:
> +               max98927->iface |= SND_SOC_DAIFMT_PDM;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       /* pcm channel configuration */
> +       if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0020_PCM_MODE_CFG,
> +                       MAX98927_PCM_MODE_CFG_FORMAT_MASK,
> +                       format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 0);
> +
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);
> +
> +       /* pdm channel configuration */
> +       if (max98927->iface & SND_SOC_DAIFMT_PDM) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 1);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 3);
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 0);
> +       return 0;
> +}
> +
> +/* codec MCLK rate in master mode */
> +static const int rate_table[] = {
> +       5644800, 6000000, 6144000, 6500000,
> +       9600000, 11289600, 12000000, 12288000,
> +       13000000, 19200000,
> +};
> +
> +static int max98927_set_clock(struct max98927_priv *max98927,
> +       struct snd_pcm_hw_params *params)
> +{
> +       struct snd_soc_codec *codec = max98927->codec;
> +       /* BCLK/LRCLK ratio calculation */
> +       int blr_clk_ratio = params_channels(params) * max98927->ch_size;
> +       int value;
> +
> +       if (max98927->master) {
> +               int i;
> +               /* match rate to closest value */
> +               for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
> +                       if (rate_table[i] >= max98927->sysclk)
> +                               break;
> +               }
> +               if (i == ARRAY_SIZE(rate_table)) {
> +                       dev_err(codec->dev, "failed to find proper clock rate.\n");
> +                       return -EINVAL;
> +               }
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0021_PCM_MASTER_MODE,
> +                       MAX98927_PCM_MASTER_MODE_MCLK_MASK,
> +                       i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
> +       }
> +
> +       switch (blr_clk_ratio) {
> +       case 32:
> +               value = 2;
> +               break;
> +       case 48:
> +               value = 3;
> +               break;
> +       case 64:
> +               value = 4;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0022_PCM_CLK_SETUP,
> +               MAX98927_PCM_CLK_SETUP_BSEL_MASK,
> +               value);
> +       return 0;
> +}
> +
> +static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
> +       struct snd_pcm_hw_params *params,
> +       struct snd_soc_dai *dai)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int sampling_rate = 0;
> +       unsigned int chan_sz = 0;
> +
> +       /* pcm mode configuration */
> +       switch (snd_pcm_format_width(params_format(params))) {
> +       case 16:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
> +               break;
> +       case 24:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
> +               break;
> +       case 32:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
> +               break;
> +       default:
> +               dev_err(codec->dev, "format unsupported %d",
> +                       params_format(params));
> +               goto err;
> +       }
> +
> +       max98927->ch_size = snd_pcm_format_width(params_format(params));
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
> +
> +       dev_dbg(codec->dev, "format supported %d",
> +               params_format(params));
> +
> +       /* sampling rate configuration */
> +       switch (params_rate(params)) {
> +       case 8000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_8000;
> +               break;
> +       case 11025:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_11025;
> +               break;
> +       case 12000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_12000;
> +               break;
> +       case 16000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_16000;
> +               break;
> +       case 22050:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_22050;
> +               break;
> +       case 24000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_24000;
> +               break;
> +       case 32000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_32000;
> +               break;
> +       case 44100:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_44100;
> +               break;
> +       case 48000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_48000;
> +               break;
> +       default:
> +               dev_err(codec->dev, "rate %d not supported\n",
> +                       params_rate(params));
> +               goto err;
> +       }
> +       /* set DAI_SR to correct LRCLK frequency */
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0023_PCM_SR_SETUP1,
> +               MAX98927_PCM_SR_SET1_SR_MASK,
> +               sampling_rate);
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0024_PCM_SR_SETUP2,
> +               MAX98927_PCM_SR_SET2_SR_MASK,
> +               sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT);
> +
> +       /* set sampling rate of IV */
> +       if (max98927->interleave_mode &&
> +           sampling_rate > MAX98927_PCM_SR_SET1_SR_16000)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate - 3);
> +       else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate);
> +       return max98927_set_clock(max98927, params);
> +err:
> +       return -EINVAL;
> +}
> +
> +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000
> +
> +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
> +       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
> +
> +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai,
> +       int clk_id, unsigned int freq, int dir)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->sysclk = freq;
> +       return 0;
> +}
> +
> +static const struct snd_soc_dai_ops max98927_dai_ops = {
> +       .set_sysclk = max98927_dai_set_sysclk,
> +       .set_fmt = max98927_dai_set_fmt,
> +       .hw_params = max98927_dai_hw_params,
> +};
> +
> +static int max98927_dac_event(struct snd_soc_dapm_widget *w,
> +       struct snd_kcontrol *kcontrol, int event)
> +{
> +       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       switch (event) {
> +       case SND_SOC_DAPM_POST_PMU:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 1);
> +               /* enable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 1);
> +               break;
> +       case SND_SOC_DAPM_POST_PMD:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 0);
> +               /* disable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, 0);
> +               break;
> +       default:
> +               return 0;
> +       }
> +       return 0;
> +}
> +
> +static const char * const max98927_switch_text[] = {
> +       "Left", "Right", "LeftRight"};
> +
> +static const struct soc_enum dai_sel_enum =
> +       SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
> +               3, max98927_switch_text);
> +
> +static const struct snd_kcontrol_new max98927_dai_controls =
> +       SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
> +
> +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = {
> +       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
> +       SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN,
> +               0, 0, max98927_dac_event,
> +               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
> +       SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
> +               &max98927_dai_controls),
> +       SND_SOC_DAPM_OUTPUT("BE_OUT"),
> +};
> +
> +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0);
> +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0);
> +
> +static bool max98927_readable_register(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B:
> +       case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B:
> +       case MAX98927_R002E_ICC_HIZ_MANUAL_MODE
> +               ... MAX98927_R004E_MEAS_ADC_CH2_READ:
> +       case MAX98927_R0051_BROWNOUT_STATUS
> +               ... MAX98927_R0055_BROWNOUT_LVL_HOLD:
> +       case MAX98927_R005A_BROWNOUT_LVL1_THRESH
> +               ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE:
> +       case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT
> +               ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ:
> +       case MAX98927_R00FF_GLOBAL_SHDN:
> +       case MAX98927_R0100_SOFT_RESET:
> +       case MAX98927_R01FF_REV_ID:
> +               return true;
> +       default:
> +               return false;
> +       }
> +};
> +
> +static bool max98927_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static const char * const max98927_boost_voltage_text[] = {
> +       "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
> +       "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
> +       "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
> +       "9.5V", "9.625V", "9.75V", "9.875V", "10V"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_boost_voltage,
> +               MAX98927_R0040_BOOST_CTRL0, 0,
> +               max98927_boost_voltage_text);
> +
> +static const char * const max98927_current_limit_text[] = {
> +       "1.00A", "1.10A", "1.20A", "1.30A", "1.40A", "1.50A", "1.60A", "1.70A",
> +       "1.80A", "1.90A", "2.00A", "2.10A", "2.20A", "2.30A", "2.40A", "2.50A",
> +       "2.60A", "2.70A", "2.80A", "2.90A", "3.00A", "3.10A", "3.20A", "3.30A",
> +       "3.40A", "3.50A", "3.60A", "3.70A", "3.80A", "3.90A", "4.00A", "4.10A"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_current_limit,
> +               MAX98927_R0042_BOOST_CTRL1, 1,
> +               max98927_current_limit_text);
> +
> +static const struct snd_kcontrol_new max98927_snd_controls[] = {
> +       SOC_SINGLE_TLV("Speaker Volume", MAX98927_R003C_SPK_GAIN,
> +               0, 6, 0,
> +               max98927_spk_tlv),
> +       SOC_SINGLE_TLV("Digital Volume", MAX98927_R0036_AMP_VOL_CTRL,
> +               0, (1<<MAX98927_AMP_VOL_WIDTH)-1, 0,
> +               max98927_digital_tlv),
> +       SOC_SINGLE("Amp DSP Switch", MAX98927_R0052_BROWNOUT_EN,
> +               MAX98927_BROWNOUT_DSP_SHIFT, 1, 0),
> +       SOC_SINGLE("Ramp Switch", MAX98927_R0037_AMP_DSP_CFG,
> +               MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0),
> +       SOC_SINGLE("DRE Switch", MAX98927_R0039_DRE_CTRL,
> +               MAX98927_DRE_EN_SHIFT, 1, 0),
> +       SOC_SINGLE("Volume Location Switch", MAX98927_R0036_AMP_VOL_CTRL,
> +               MAX98927_AMP_VOL_SEL_SHIFT, 1, 0),
> +       SOC_ENUM("Boost Output Voltage", max98927_boost_voltage),
> +       SOC_ENUM("Current Limit", max98927_current_limit),
> +};
> +
> +static const struct snd_soc_dapm_route max98927_audio_map[] = {
> +       {"Amp Enable", NULL, "DAI_OUT"},
> +       {"DAI Sel Mux", "Left", "Amp Enable"},
> +       {"DAI Sel Mux", "Right", "Amp Enable"},
> +       {"DAI Sel Mux", "LeftRight", "Amp Enable"},
> +       {"BE_OUT", NULL, "DAI Sel Mux"},
> +};
> +
> +static struct snd_soc_dai_driver max98927_dai[] = {
> +       {
> +               .name = "max98927-aif1",
> +               .playback = {
> +                       .stream_name = "HiFi Playback",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .capture = {
> +                       .stream_name = "HiFi Capture",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .ops = &max98927_dai_ops,
> +       }
> +};
> +
> +static int max98927_probe(struct snd_soc_codec *codec)
> +{
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->codec = codec;
> +       codec->control_data = max98927->regmap;
> +       codec->cache_bypass = 1;
> +
> +       /* Software Reset */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0100_SOFT_RESET, MAX98927_SOFT_RESET);
> +
> +       /* IV default slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               0x80);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,
> +               0x1);
> +       /* Set inital volume (+13dB) */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0036_AMP_VOL_CTRL,
> +               0x38);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003C_SPK_GAIN,
> +               0x05);
> +       /* Enable DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0037_AMP_DSP_CFG,
> +               0x03);
> +       /* Enable IMON VMON DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003F_MEAS_DSP_CFG,
> +               0xF7);
> +       /* Boost Output Voltage & Current limit */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0040_BOOST_CTRL0,
> +               0x1C);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0042_BOOST_CTRL1,
> +               0x3E);
> +       /* Measurement ADC config */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0043_MEAS_ADC_CFG,
> +               0x04);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0044_MEAS_ADC_BASE_MSB,
> +               0x00);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0045_MEAS_ADC_BASE_LSB,
> +               0x24);
> +       /* Brownout Level */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,
> +               0x06);
> +       /* Envelope Tracking configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,
> +               0x08);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0086_ENV_TRACK_CTRL,
> +               0x01);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,
> +               0x10);
> +
> +       /* voltage, current slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001E_PCM_TX_CH_SRC_A,
> +               (max98927->i_l_slot<<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT|
> +               max98927->v_l_slot)&0xFF);
> +
> +       if (max98927->v_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->v_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->v_l_slot,
> +                       1 << max98927->v_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->v_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->v_l_slot - 8),
> +                       1 << (max98927->v_l_slot - 8));
> +       }
> +
> +       if (max98927->i_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->i_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->i_l_slot,
> +                       1 << max98927->i_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->i_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->i_l_slot - 8),
> +                       1 << (max98927->i_l_slot - 8));
> +       }
> +
> +       /* Set interleave mode */
> +       if (max98927->interleave_mode)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001F_PCM_TX_CH_SRC_B,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK);
> +       return 0;
> +}
> +
> +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = {
> +       .probe = max98927_probe,
> +       .component_driver = {
> +               .controls = max98927_snd_controls,
> +               .num_controls = ARRAY_SIZE(max98927_snd_controls),
> +               .dapm_widgets = max98927_dapm_widgets,
> +               .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets),
> +               .dapm_routes = max98927_audio_map,
> +               .num_dapm_routes = ARRAY_SIZE(max98927_audio_map),
> +       },
> +};
> +
> +static const struct regmap_config max98927_regmap = {
> +       .reg_bits         = 16,
> +       .val_bits         = 8,
> +       .max_register     = MAX98927_R01FF_REV_ID,
> +       .reg_defaults     = max98927_reg,
> +       .num_reg_defaults = ARRAY_SIZE(max98927_reg),
> +       .readable_reg     = max98927_readable_register,
> +       .volatile_reg     = max98927_volatile_reg,
> +       .cache_type       = REGCACHE_RBTREE,
> +};
> +
> +static void max98927_slot_config(struct i2c_client *i2c,
> +       struct max98927_priv *max98927)
> +{
> +       int value;
> +
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "vmon-slot-no", &value))
> +               max98927->v_l_slot = value & 0xF;
> +       else
> +               max98927->v_l_slot = 0;
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "imon-slot-no", &value))
> +               max98927->i_l_slot = value & 0xF;
> +       else
> +               max98927->i_l_slot = 1;
> +}
> +
> +static int max98927_i2c_probe(struct i2c_client *i2c,
> +       const struct i2c_device_id *id)
> +{
> +
> +       int ret = 0, value;
> +       int reg = 0;
> +       struct max98927_priv *max98927 = NULL;
> +
> +       max98927 = devm_kzalloc(&i2c->dev,
> +               sizeof(*max98927), GFP_KERNEL);
> +
> +       if (!max98927) {
> +               ret = -ENOMEM;
> +               return ret;
> +       }
> +       i2c_set_clientdata(i2c, max98927);
> +
> +       /* update interleave mode info */
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "interleave_mode", &value)) {
> +               if (value > 0)
> +                       max98927->interleave_mode = 1;
> +               else
> +                       max98927->interleave_mode = 0;
> +       } else
> +               max98927->interleave_mode = 0;
> +
> +       /* regmap initialization */
> +       max98927->regmap
> +               = devm_regmap_init_i2c(i2c, &max98927_regmap);
> +       if (IS_ERR(max98927->regmap)) {
> +               ret = PTR_ERR(max98927->regmap);
> +               dev_err(&i2c->dev,
> +                       "Failed to allocate regmap: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* Check Revision ID */
> +       ret = regmap_read(max98927->regmap,
> +               MAX98927_R01FF_REV_ID, &reg);
> +       if (ret < 0) {
> +               dev_err(&i2c->dev,
> +                       "Failed to read: 0x%02X\n", MAX98927_R01FF_REV_ID);
> +               return ret;
> +       }
> +       dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n", reg);
> +
> +       /* voltage/current slot configuration */
> +       max98927_slot_config(i2c, max98927);
> +
> +       /* codec registeration */
> +       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927,
> +               max98927_dai, ARRAY_SIZE(max98927_dai));
> +       if (ret < 0)
> +               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static int max98927_i2c_remove(struct i2c_client *client)
> +{
> +       snd_soc_unregister_codec(&client->dev);
> +       return 0;
> +}
> +
> +static const struct i2c_device_id max98927_i2c_id[] = {
> +       { "max98927", 0},
> +       { },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id max98927_of_match[] = {
> +       { .compatible = "maxim,max98927", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, max98927_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id max98927_acpi_match[] = {
> +       { "MX98927", 0 },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(acpi, max98927_acpi_match);
> +#endif
> +
> +static struct i2c_driver max98927_i2c_driver = {
> +       .driver = {
> +               .name = "max98927",
> +               .of_match_table = of_match_ptr(max98927_of_match),
> +               .acpi_match_table = ACPI_PTR(max98927_acpi_match),
> +               .pm = NULL,
> +       },
> +       .probe  = max98927_i2c_probe,
> +       .remove = max98927_i2c_remove,
> +       .id_table = max98927_i2c_id,
> +};
> +
> +module_i2c_driver(max98927_i2c_driver)
> +
> +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver");
> +MODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h
> new file mode 100644
> index 000000000000..ece6a608cbe1
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.h
> @@ -0,0 +1,272 @@
> +/*
> + * max98927.h  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright 2013-15 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee@maximintegrated.com>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + */
> +#ifndef _MAX98927_H
> +#define _MAX98927_H
> +
> +/* Register Values */
> +#define MAX98927_R0001_INT_RAW1 0x0001
> +#define MAX98927_R0002_INT_RAW2 0x0002
> +#define MAX98927_R0003_INT_RAW3 0x0003
> +#define MAX98927_R0004_INT_STATE1 0x0004
> +#define MAX98927_R0005_INT_STATE2 0x0005
> +#define MAX98927_R0006_INT_STATE3 0x0006
> +#define MAX98927_R0007_INT_FLAG1 0x0007
> +#define MAX98927_R0008_INT_FLAG2 0x0008
> +#define MAX98927_R0009_INT_FLAG3 0x0009
> +#define MAX98927_R000A_INT_EN1 0x000A
> +#define MAX98927_R000B_INT_EN2 0x000B
> +#define MAX98927_R000C_INT_EN3 0x000C
> +#define MAX98927_R000D_INT_FLAG_CLR1   0x000D
> +#define MAX98927_R000E_INT_FLAG_CLR2   0x000E
> +#define MAX98927_R000F_INT_FLAG_CLR3   0x000F
> +#define MAX98927_R0010_IRQ_CTRL 0x0010
> +#define MAX98927_R0011_CLK_MON 0x0011
> +#define MAX98927_R0012_WDOG_CTRL 0x0012
> +#define MAX98927_R0013_WDOG_RST 0x0013
> +#define MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH 0x0014
> +#define MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH 0x0015
> +#define MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS 0x0016
> +#define MAX98927_R0017_PIN_CFG 0x0017
> +#define MAX98927_R0018_PCM_RX_EN_A 0x0018
> +#define MAX98927_R0019_PCM_RX_EN_B 0x0019
> +#define MAX98927_R001A_PCM_TX_EN_A 0x001A
> +#define MAX98927_R001B_PCM_TX_EN_B 0x001B
> +#define MAX98927_R001C_PCM_TX_HIZ_CTRL_A 0x001C
> +#define MAX98927_R001D_PCM_TX_HIZ_CTRL_B 0x001D
> +#define MAX98927_R001E_PCM_TX_CH_SRC_A 0x001E
> +#define MAX98927_R001F_PCM_TX_CH_SRC_B 0x001F
> +#define MAX98927_R0020_PCM_MODE_CFG 0x0020
> +#define MAX98927_R0021_PCM_MASTER_MODE 0x0021
> +#define MAX98927_R0022_PCM_CLK_SETUP 0x0022
> +#define MAX98927_R0023_PCM_SR_SETUP1 0x0023
> +#define MAX98927_R0024_PCM_SR_SETUP2   0x0024
> +#define MAX98927_R0025_PCM_TO_SPK_MONOMIX_A 0x0025
> +#define MAX98927_R0026_PCM_TO_SPK_MONOMIX_B 0x0026
> +#define MAX98927_R0027_ICC_RX_EN_A 0x0027
> +#define MAX98927_R0028_ICC_RX_EN_B 0x0028
> +#define MAX98927_R002B_ICC_TX_EN_A 0x002B
> +#define MAX98927_R002C_ICC_TX_EN_B 0x002C
> +#define MAX98927_R002E_ICC_HIZ_MANUAL_MODE 0x002E
> +#define MAX98927_R002F_ICC_TX_HIZ_EN_A 0x002F
> +#define MAX98927_R0030_ICC_TX_HIZ_EN_B 0x0030
> +#define MAX98927_R0031_ICC_LNK_EN 0x0031
> +#define MAX98927_R0032_PDM_TX_EN 0x0032
> +#define MAX98927_R0033_PDM_TX_HIZ_CTRL 0x0033
> +#define MAX98927_R0034_PDM_TX_CTRL 0x0034
> +#define MAX98927_R0035_PDM_RX_CTRL 0x0035
> +#define MAX98927_R0036_AMP_VOL_CTRL 0x0036
> +#define MAX98927_R0037_AMP_DSP_CFG 0x0037
> +#define MAX98927_R0038_TONE_GEN_DC_CFG 0x0038
> +#define MAX98927_R0039_DRE_CTRL 0x0039
> +#define MAX98927_R003A_AMP_EN 0x003A
> +#define MAX98927_R003B_SPK_SRC_SEL 0x003B
> +#define MAX98927_R003C_SPK_GAIN 0x003C
> +#define MAX98927_R003D_SSM_CFG 0x003D
> +#define MAX98927_R003E_MEAS_EN 0x003E
> +#define MAX98927_R003F_MEAS_DSP_CFG 0x003F
> +#define MAX98927_R0040_BOOST_CTRL0 0x0040
> +#define MAX98927_R0041_BOOST_CTRL3 0x0041
> +#define MAX98927_R0042_BOOST_CTRL1 0x0042
> +#define MAX98927_R0043_MEAS_ADC_CFG 0x0043
> +#define MAX98927_R0044_MEAS_ADC_BASE_MSB 0x0044
> +#define MAX98927_R0045_MEAS_ADC_BASE_LSB 0x0045
> +#define MAX98927_R0046_ADC_CH0_DIVIDE 0x0046
> +#define MAX98927_R0047_ADC_CH1_DIVIDE 0x0047
> +#define MAX98927_R0048_ADC_CH2_DIVIDE 0x0048
> +#define MAX98927_R0049_ADC_CH0_FILT_CFG 0x0049
> +#define MAX98927_R004A_ADC_CH1_FILT_CFG 0x004A
> +#define MAX98927_R004B_ADC_CH2_FILT_CFG 0x004B
> +#define MAX98927_R004C_MEAS_ADC_CH0_READ 0x004C
> +#define MAX98927_R004D_MEAS_ADC_CH1_READ 0x004D
> +#define MAX98927_R004E_MEAS_ADC_CH2_READ 0x004E
> +#define MAX98927_R0051_BROWNOUT_STATUS 0x0051
> +#define MAX98927_R0052_BROWNOUT_EN 0x0052
> +#define MAX98927_R0053_BROWNOUT_INFINITE_HOLD 0x0053
> +#define MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR 0x0054
> +#define MAX98927_R0055_BROWNOUT_LVL_HOLD 0x0055
> +#define MAX98927_R005A_BROWNOUT_LVL1_THRESH 0x005A
> +#define MAX98927_R005B_BROWNOUT_LVL2_THRESH 0x005B
> +#define MAX98927_R005C_BROWNOUT_LVL3_THRESH 0x005C
> +#define MAX98927_R005D_BROWNOUT_LVL4_THRESH 0x005D
> +#define MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS 0x005E
> +#define MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL 0x005F
> +#define MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL 0x0060
> +#define MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE 0x0061
> +#define MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 0x0072
> +#define MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1 0x0073
> +#define MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2 0x0074
> +#define MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3 0x0075
> +#define MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT 0x0076
> +#define MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1 0x0077
> +#define MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2 0x0078
> +#define MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3 0x0079
> +#define MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT 0x007A
> +#define MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1 0x007B
> +#define MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2 0x007C
> +#define MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3 0x007D
> +#define MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT 0x007E
> +#define MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1 0x007F
> +#define MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2 0x0080
> +#define MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3 0x0081
> +#define MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM 0x0082
> +#define MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY 0x0083
> +#define MAX98927_R0084_ENV_TRACK_REL_RATE 0x0084
> +#define MAX98927_R0085_ENV_TRACK_HOLD_RATE 0x0085
> +#define MAX98927_R0086_ENV_TRACK_CTRL 0x0086
> +#define MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ 0x0087
> +#define MAX98927_R00FF_GLOBAL_SHDN 0x00FF
> +#define MAX98927_R0100_SOFT_RESET 0x0100
> +#define MAX98927_R01FF_REV_ID 0x01FF
> +
> +/* MAX98927_R0018_PCM_RX_EN_A */
> +#define MAX98927_PCM_RX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_RX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_RX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_RX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_RX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_RX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_RX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_RX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001A_PCM_TX_EN_A */
> +#define MAX98927_PCM_TX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_TX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_TX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_TX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_TX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_TX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_TX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_TX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001E_PCM_TX_CH_SRC_A */
> +#define MAX98927_PCM_TX_CH_SRC_A_V_SHIFT (0)
> +#define MAX98927_PCM_TX_CH_SRC_A_I_SHIFT (4)
> +
> +/* MAX98927_R001F_PCM_TX_CH_SRC_B */
> +#define MAX98927_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 5)
> +
> +/* MAX98927_R0020_PCM_MODE_CFG */
> +#define MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3)
> +#define MAX98927_PCM_FORMAT_I2S (0x0 << 0)
> +#define MAX98927_PCM_FORMAT_LJ (0x1 << 0)
> +
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
> +
> +/* MAX98927_R0021_PCM_MASTER_MODE */
> +#define MAX98927_PCM_MASTER_MODE_MASK (0x3 << 0)
> +#define MAX98927_PCM_MASTER_MODE_SLAVE (0x0 << 0)
> +#define MAX98927_PCM_MASTER_MODE_MASTER (0x3 << 0)
> +
> +#define MAX98927_PCM_MASTER_MODE_MCLK_MASK (0xF << 2)
> +#define MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2)
> +
> +/* MAX98927_R0022_PCM_CLK_SETUP */
> +#define MAX98927_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
> +
> +/* MAX98927_R0023_PCM_SR_SETUP1 */
> +#define MAX98927_PCM_SR_SET1_SR_MASK (0xF << 0)
> +
> +#define MAX98927_PCM_SR_SET1_SR_8000 (0x0 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_11025 (0x1 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_12000 (0x2 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_16000 (0x3 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_22050 (0x4 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_24000 (0x5 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_32000 (0x6 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_44100 (0x7 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_48000 (0x8 << 0)
> +
> +/* MAX98927_R0024_PCM_SR_SETUP2 */
> +#define MAX98927_PCM_SR_SET2_SR_MASK (0xF << 4)
> +#define MAX98927_PCM_SR_SET2_SR_SHIFT (4)
> +#define MAX98927_PCM_SR_SET2_IVADC_SR_MASK (0xf << 0)
> +
> +/* MAX98927_R0025_PCM_TO_SPK_MONOMIX_A */
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
> +
> +/* MAX98927_R0035_PDM_RX_CTRL */
> +#define MAX98927_PDM_RX_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R0036_AMP_VOL_CTRL */
> +#define MAX98927_AMP_VOL_SEL (0x1 << 7)
> +#define MAX98927_AMP_VOL_SEL_WIDTH (1)
> +#define MAX98927_AMP_VOL_SEL_SHIFT (7)
> +#define MAX98927_AMP_VOL_MASK (0x7f << 0)
> +#define MAX98927_AMP_VOL_WIDTH (7)
> +#define MAX98927_AMP_VOL_SHIFT (0)
> +
> +/* MAX98927_R0037_AMP_DSP_CFG */
> +#define MAX98927_AMP_DSP_CFG_DCBLK_EN (0x1 << 0)
> +#define MAX98927_AMP_DSP_CFG_DITH_EN (0x1 << 1)
> +#define MAX98927_AMP_DSP_CFG_RMP_BYPASS (0x1 << 4)
> +#define MAX98927_AMP_DSP_CFG_DAC_INV (0x1 << 5)
> +#define MAX98927_AMP_DSP_CFG_RMP_SHIFT (4)
> +
> +/* MAX98927_R0039_DRE_CTRL */
> +#define MAX98927_DRE_CTRL_DRE_EN       (0x1 << 0)
> +#define MAX98927_DRE_EN_SHIFT 0x1
> +
> +/* MAX98927_R003A_AMP_EN */
> +#define MAX98927_AMP_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R003B_SPK_SRC_SEL */
> +#define MAX98927_SPK_SRC_MASK (0x3 << 0)
> +
> +/* MAX98927_R003C_SPK_GAIN */
> +#define MAX98927_SPK_PCM_GAIN_MASK (0x7 << 0)
> +#define MAX98927_SPK_PDM_GAIN_MASK (0x7 << 4)
> +#define MAX98927_SPK_GAIN_WIDTH (3)
> +
> +/* MAX98927_R003E_MEAS_EN */
> +#define MAX98927_MEAS_V_EN (0x1 << 0)
> +#define MAX98927_MEAS_I_EN (0x1 << 1)
> +
> +/* MAX98927_R0040_BOOST_CTRL0 */
> +#define MAX98927_BOOST_CTRL0_VOUT_MASK (0x1f << 0)
> +#define MAX98927_BOOST_CTRL0_PVDD_MASK (0x1 << 7)
> +#define MAX98927_BOOST_CTRL0_PVDD_EN_SHIFT (7)
> +
> +/* MAX98927_R0052_BROWNOUT_EN */
> +#define MAX98927_BROWNOUT_BDE_EN (0x1 << 0)
> +#define MAX98927_BROWNOUT_AMP_EN (0x1 << 1)
> +#define MAX98927_BROWNOUT_DSP_EN (0x1 << 2)
> +#define MAX98927_BROWNOUT_DSP_SHIFT (2)
> +
> +/* MAX98927_R0100_SOFT_RESET */
> +#define MAX98927_SOFT_RESET (0x1 << 0)
> +
> +/* MAX98927_R00FF_GLOBAL_SHDN */
> +#define MAX98927_GLOBAL_EN_MASK (0x1 << 0)
> +
> +struct max98927_priv {
> +       struct regmap *regmap;
> +       struct snd_soc_codec *codec;
> +       struct max98927_pdata *pdata;
> +       unsigned int spk_gain;
> +       unsigned int sysclk;
> +       unsigned int v_l_slot;
> +       unsigned int i_l_slot;
> +       bool interleave_mode;
> +       unsigned int ch_size;
> +       unsigned int rate;
> +       unsigned int iface;
> +       unsigned int master;
> +       unsigned int digital_gain;
> +};
> +#endif
> --
> 2.11.0
>

^ permalink raw reply

* [PATCH 01/10] clk: renesas: cpg-mssr: Document R-Car Gen2 support
From: Geert Uytterhoeven @ 2017-04-25 16:53 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
	Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1493139200-27396-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>

Document use of the Renesas Clock Pulse Generator / Module Standby and
Software Reset DT Bindings for various member of the R-Car Gen2 family
(H2, M2-W, V2H, M2-N, and E2).

Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
 Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
index f4f944d813081857..0cd894f987a38e81 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
@@ -15,6 +15,11 @@ Required Properties:
   - compatible: Must be one of:
       - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
       - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
+      - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
+      - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
+      - "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H)
+      - "renesas,r8a7793-cpg-mssr" for the r8a7793 SoC (R-Car M2-N)
+      - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
@@ -24,9 +29,10 @@ Required Properties:
   - clocks: References to external parent clocks, one entry for each entry in
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
-      - "extal" (r8a7743, r8a7745, r8a7795, r8a7796)
+      - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
+		 r8a7795, r8a7796)
       - "extalr" (r8a7795, r8a7796)
-      - "usb_extal" (r8a7743, r8a7745)
+      - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 06/13] MIPS: lantiq: Convert the xbar driver to a platform_driver
From: Rob Herring @ 2017-04-25 16:57 UTC (permalink / raw)
  To: Hauke Mehrtens
  Cc: Ralf Baechle, Linux-MIPS,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	LINUX-WATCHDOG,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Martin Blumenstingl, John Crispin,
	linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	hauke.mehrtens-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <8742e3b3-4dc2-bc74-f607-00d96f74512c-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>

On Tue, Apr 25, 2017 at 1:56 AM, Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org> wrote:
>
>
> On 04/20/2017 04:48 PM, Rob Herring wrote:
>> On Mon, Apr 17, 2017 at 09:29:35PM +0200, Hauke Mehrtens wrote:
>>> From: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>>
>>> This allows using the xbar driver on ARX300 based SoCs which require the
>>> same xbar setup as the xRX200 chipsets because the xbar driver
>>> initialization is not guarded by an xRX200 specific
>>> of_machine_is_compatible condition anymore. Additionally the new driver
>>> takes a syscon phandle to configure the XBAR endianness bits in RCU
>>> (before this was done in arch/mips/lantiq/xway/reset.c and also
>>> guarded by an xRX200 specific if-statement).
>>>
>>> Signed-off-by: Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>>> ---
>>>  .../devicetree/bindings/mips/lantiq/xbar.txt       |  22 +++++
>>>  MAINTAINERS                                        |   1 +
>>>  arch/mips/lantiq/xway/reset.c                      |   4 -
>>>  arch/mips/lantiq/xway/sysctrl.c                    |  41 ---------
>>>  drivers/soc/Makefile                               |   1 +
>>>  drivers/soc/lantiq/Makefile                        |   1 +
>>>  drivers/soc/lantiq/xbar.c                          | 100 +++++++++++++++++++++
>>>  7 files changed, 125 insertions(+), 45 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>>  create mode 100644 drivers/soc/lantiq/Makefile
>>>  create mode 100644 drivers/soc/lantiq/xbar.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/mips/lantiq/xbar.txt b/Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>> new file mode 100644
>>> index 000000000000..86e53ff3b0d5
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>> @@ -0,0 +1,22 @@
>>> +Lantiq XWAY SoC XBAR binding
>>> +============================
>>> +
>>> +
>>> +-------------------------------------------------------------------------------
>>> +Required properties:
>>> +- compatible        : Should be "lantiq,xbar-xway"
>>
>> This compatible is already in use so it is fine, but you should also
>> have per SoC compatible strings.
>
> I will add a new SoC specific one.
> What does per SoC device tree mean? Does it mean for the same silicon,
> for the same silicon revision, for the same fusing of a silicon or for
> the same marketing name?

Depends how specific you need to some extent. For fusing, packaging,
metal fixes, speed grading, etc. probably use the same compatible.
Different design and dies from the start, then they should have
different compatibles.

> I would like to make it per silicon or per silicon revision for the IP
> cores which I know are different.

Being "the same IP" doesn't really matter. The errata can be different
and often there is no visibility into what h/w designers may have
changed. On some IP you can rely on revision/feature registers though
forgetting to rev revision registers is not uncommon. You need to have
sufficient information that you can work-around a problem in the
future without requiring a new dtb.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 08/13] reset: Add a reset controller driver for the Lantiq XWAY based SoCs
From: Rob Herring @ 2017-04-25 17:01 UTC (permalink / raw)
  To: Hauke Mehrtens
  Cc: Ralf Baechle, Linux-MIPS,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	LINUX-WATCHDOG,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Martin Blumenstingl, John Crispin,
	linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	hauke.mehrtens-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <a9519140-a804-9888-3223-9a1446e25c52-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>

On Tue, Apr 25, 2017 at 2:00 AM, Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org> wrote:
>
>
> On 04/20/2017 04:54 PM, Rob Herring wrote:
>> On Mon, Apr 17, 2017 at 09:29:37PM +0200, Hauke Mehrtens wrote:
>>> From: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>>
>>> The reset controllers (on xRX200 and newer SoCs have two of them) are
>>> provided by the RCU module. This was initially implemented as a simple
>>> reset controller. However, the RCU module provides more functionality
>>> (ethernet GPHYs, USB PHY, etc.), which makes it a MFD device.
>>> The old reset controller driver implementation from
>>> arch/mips/lantiq/xway/reset.c did not honor this fact.
>>>
>>> For some devices the request and the status bits are different.
>>>
>>> Signed-off-by: Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>>> ---
>>>  .../devicetree/bindings/reset/lantiq,rcu-reset.txt |  43 ++++
>>>  arch/mips/lantiq/xway/reset.c                      |  68 ------
>>>  drivers/reset/Kconfig                              |   6 +
>>>  drivers/reset/Makefile                             |   1 +
>>>  drivers/reset/reset-lantiq-rcu.c                   | 231 +++++++++++++++++++++
>>>  5 files changed, 281 insertions(+), 68 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>>  create mode 100644 drivers/reset/reset-lantiq-rcu.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt b/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>> new file mode 100644
>>> index 000000000000..7f097d16bbb7
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>> @@ -0,0 +1,43 @@
>>> +Lantiq XWAY SoC RCU reset controller binding
>>> +============================================
>>> +
>>> +This binding describes a reset-controller found on the RCU module on Lantiq
>>> +XWAY SoCs.
>>> +
>>> +
>>> +-------------------------------------------------------------------------------
>>> +Required properties (controller (parent) node):
>>> +- compatible                : Should be "lantiq,rcu-reset"
>>> +- lantiq,rcu-syscon : A phandle to the RCU syscon, the reset register
>>> +                      offset and the status register offset.
>>> +- #reset-cells              : Specifies the number of cells needed to encode the
>>> +                      reset line, should be 1.
>>> +
>>> +Optional properties:
>>> +- reset-status              : The request status bit. For some bits the request bit
>>> +                      and the status bit are different. This is depending
>>> +                      on the SoC. If the reset-status bit does not match
>>> +                      the reset-request bit, put the reset number into the
>>> +                      reset-request property and the status bit at the same
>>> +                      index into the reset-status property. If no
>>> +                      reset-request bit is given here, the driver assume
>>> +                      status and request bit are the same.
>>> +- reset-request             : The reset request bit, to map it to the reset-status
>>> +                      bit.
>>
>> These should either be implied by SoC specific compatible or be made
>> part of the reset cells. In the latter case, you still need the SoC
>> specific compatible.
>
> Currently the reset framework only supports a single reset cell to my
> knowledge, but I haven't looked into the details, I could extend it to
> make it support two.

I thought we had cases already, but maybe I'm thinking of something
else. In any case, driver limitations shouldn't define binding design.

> The SoC which needs this has two reset control register sets and the
> bits are specific for each register set. Would a specific compatible
> string for each register set ok?

Yes. You should have that.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] clk: Provide dummy of_clk_get_from_provider() for compile-testing
From: Geert Uytterhoeven @ 2017-04-25 17:28 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Russell King, Rob Herring,
	Mark Rutland
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven

When CONFIG_ON=n, dummies are provided for of_clk_get() and
of_clk_get_by_name(), but not for of_clk_get_from_provider().

Provide a dummy for the latter, to improve the ability to do
compile-testing.

Fixes: 766e6a4ec602d0c1 ("clk: add DT clock binding support")
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
 include/linux/clk.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/clk.h b/include/linux/clk.h
index e9d36b3e49de5b1b..3ed97abb5cbb7f94 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -539,6 +539,10 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
 {
 	return ERR_PTR(-ENOENT);
 }
+static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
+{
+	return ERR_PTR(-ENOENT);
+}
 #endif
 
 #endif
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH] of: Provide dummy of_device_compatible_match() for compile-testing
From: Geert Uytterhoeven @ 2017-04-25 17:38 UTC (permalink / raw)
  To: Rob Herring, Frank Rowand
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven

Most of_device_*() functions have dummy versions for CONFIG_OF=n,
but of_device_compatible_match() hasn't.  Fix that to improve the
ability to do compile-testing.

Fixes: b9c13fe32faaa71c ("dt: Add of_device_compatible_match()")
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
 include/linux/of.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/of.h b/include/linux/of.h
index 21e6323de0f3b786..bfd1a23221735161 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -620,6 +620,12 @@ static inline int of_device_is_compatible(const struct device_node *device,
 	return 0;
 }
 
+static inline  int of_device_compatible_match(struct device_node *device,
+					      const char *const *compat)
+{
+	return 0;
+}
+
 static inline bool of_device_is_available(const struct device_node *device)
 {
 	return false;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH] of: Introduce of_node_get_match_data() helper
From: Geert Uytterhoeven @ 2017-04-25 17:40 UTC (permalink / raw)
  To: Rob Herring, Frank Rowand; +Cc: devicetree, linux-kernel, Geert Uytterhoeven

If CONFIG_OF=n, code using

    info = of_match_node(matchs, np)->data;

fails to compile:

    warning: dereferencing ‘void *’ pointer
    error: request for member ‘data’ in something not a structure or union

Follow the example set by of_device_get_match_data(), and introduce a
new helper of_node_get_match_data().  This will allow to increase
compile-testing coverage later.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/of/base.c  | 13 +++++++++++++
 include/linux/of.h |  7 +++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index d7c4629a3a2decb6..473d002ba7203115 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1022,6 +1022,19 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 }
 EXPORT_SYMBOL(of_match_node);
 
+const void *of_node_get_match_data(const struct of_device_id *matches,
+				   const struct device_node *node)
+{
+	const struct of_device_id *match;
+
+	match = of_match_node(matches, node);
+	if (!match)
+		return NULL;
+
+	return match->data;
+}
+EXPORT_SYMBOL(of_node_get_match_data);
+
 /**
  *	of_find_matching_node_and_match - Find a node based on an of_device_id
  *					  match table.
diff --git a/include/linux/of.h b/include/linux/of.h
index bfd1a23221735161..214e41eac4e5634f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -337,6 +337,8 @@ extern int of_n_addr_cells(struct device_node *np);
 extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
 	const struct of_device_id *matches, const struct device_node *node);
+extern const void *of_node_get_match_data(const struct of_device_id *matches,
+					  const struct device_node *node);
 extern int of_modalias_node(struct device_node *node, char *modalias, int len);
 extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
 extern struct device_node *of_parse_phandle(const struct device_node *np,
@@ -844,8 +846,9 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
 {
 }
 
-#define of_match_ptr(_ptr)	NULL
-#define of_match_node(_matches, _node)	NULL
+#define of_match_ptr(_ptr)			NULL
+#define of_match_node(_matches, _node)		NULL
+#define of_node_get_match_data(_matches, _node)	NULL
 #endif /* CONFIG_OF */
 
 /* Default string compare functions, Allow arch asm/prom.h to override */
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v2 2/2] of: Add unit tests for applying overlays
From: Frank Rowand @ 2017-04-25 17:45 UTC (permalink / raw)
  To: Rob Herring
  Cc: Stephen Boyd, Michal Marek,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Linux Kbuild mailing list
In-Reply-To: <CAL_Jsq+8fcDwe4iPxLRsKnw_UAc6JE3KRRbnx1aS+o0oJH9tPw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 04/25/17 09:44, Rob Herring wrote:
> On Mon, Apr 24, 2017 at 6:05 PM,  <frowand.list-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> From: Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>
>>
>> Existing overlay unit tests examine individual pieces of the overlay
>> code.  The new tests target the entire process of applying an overlay.
> 
> Just a few nits.
> 
>> Signed-off-by: Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>
> 
> [...]
> 
>> diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
>> index 18bbb4517e25..cc76b3b81eab 100644
>> --- a/drivers/of/of_private.h
>> +++ b/drivers/of/of_private.h
>> @@ -55,6 +55,17 @@ static inline int of_property_notify(int action, struct device_node *np,
>>  }
>>  #endif /* CONFIG_OF_DYNAMIC */
>>
>> +#ifdef CONFIG_OF_UNITTEST
>> +extern void __init unittest_unflatten_overlay_base(void);
>> +extern void *__unflatten_device_tree(const void *blob,
> 
> This can and should be outside the ifdef.

Will do.

> 
>> +                             struct device_node *dad,
>> +                             struct device_node **mynodes,
>> +                             void *(*dt_alloc)(u64 size, u64 align),
>> +                             bool detached);
>> +#else
>> +static inline void unittest_unflatten_overlay_base(void) {};
>> +#endif
>> +
>>  /**
>>   * General utilities for working with live trees.
>>   *
> 
> [...]
> 
>> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
>> index 62db55b97c10..884f6c1f8ae9 100644
>> --- a/drivers/of/unittest.c
>> +++ b/drivers/of/unittest.c
>> @@ -8,6 +8,7 @@
>>  #include <linux/err.h>
>>  #include <linux/errno.h>
>>  #include <linux/hashtable.h>
>> +#include <linux/libfdt.h>
>>  #include <linux/of.h>
>>  #include <linux/of_fdt.h>
>>  #include <linux/of_irq.h>
>> @@ -1925,6 +1926,320 @@ static void __init of_unittest_overlay(void)
>>  static inline void __init of_unittest_overlay(void) { }
>>  #endif
>>
>> +#ifdef CONFIG_OF_OVERLAY
> 
> This can move down to...

Will do.

> 
>> +
>> +/*
>> + * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
>> + * in scripts/Makefile.lib
>> + */
>> +
>> +#define OVERLAY_INFO_EXTERN(name) \
>> +       extern uint8_t __dtb_##name##_begin[]; \
>> +       extern uint8_t __dtb_##name##_end[]
>> +
>> +#define OVERLAY_INFO(name, expected) \
>> +{      .dtb_begin       = __dtb_##name##_begin, \
>> +       .dtb_end         = __dtb_##name##_end, \
>> +       .expected_result = expected, \
>> +}
>> +
>> +struct overlay_info {
>> +       uint8_t            *dtb_begin;
>> +       uint8_t            *dtb_end;
>> +       void               *data;
>> +       struct device_node *np_overlay;
>> +       int                expected_result;
>> +       int                overlay_id;
>> +};
>> +
>> +OVERLAY_INFO_EXTERN(overlay_base);
>> +OVERLAY_INFO_EXTERN(overlay);
>> +OVERLAY_INFO_EXTERN(overlay_bad_phandle);
> 
> ...here. Maybe we want to move all this to a separate file instead.

In the medium term, yes.  At the moment it is good enough for this
localized use for unittest.  I do not think it is baked enough
for general use.  I want to see how well it works for the
previously existing overlay unit tests and make sure it meets
the majority of the needs of wider use cases before making it
more widely visible.


>> +
>> +/* order of entries is hard-coded into users of overlays[] */
>> +struct overlay_info overlays[] = {
> 
> static?

Yes, thanks.


>> +       OVERLAY_INFO(overlay_base, -9999),
>> +       OVERLAY_INFO(overlay, 0),
>> +       OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
>> +       {}
>> +};
> 
> [...]
> 
>> @@ -1962,6 +2277,9 @@ static int __init of_unittest(void)
>>         /* Double check linkage after removing testcase data */
>>         of_unittest_check_tree_linkage();
>>
>> +
> 
> Extra blank line.

thanks

> 
>> +       of_unittest_overlay_high_level();
>> +
>>         pr_info("end of unittest - %i passed, %i failed\n",
>>                 unittest_results.passed, unittest_results.failed);
>>
>> --
>> Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>
>>
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver
From: Andy Shevchenko @ 2017-04-25 18:12 UTC (permalink / raw)
  To: Eugeniy Paltsev
  Cc: vinod.koul@intel.com, linux-kernel@vger.kernel.org,
	robh+dt@kernel.org, Alexey.Brodkin@synopsys.com,
	devicetree@vger.kernel.org, linux-snps-arc@lists.infradead.org,
	dan.j.williams@intel.com, dmaengine@vger.kernel.org
In-Reply-To: <1493133369.25985.10.camel@synopsys.com>

On Tue, 2017-04-25 at 15:16 +0000, Eugeniy Paltsev wrote:
> On Mon, 2017-04-24 at 19:56 +0300, Andy Shevchenko wrote:
> > On Mon, 2017-04-24 at 15:55 +0000, Eugeniy Paltsev wrote:
> > > Hi,
> > > On Fri, 2017-04-21 at 18:13 +0300, Andy Shevchenko wrote:
> > > > On Fri, 2017-04-21 at 14:29 +0000, Eugeniy Paltsev wrote:
> > > > > On Tue, 2017-04-18 at 15:31 +0300, Andy Shevchenko wrote:
> > > > > > On Fri, 2017-04-07 at 17:04 +0300, Eugeniy Paltsev wrote:

> > > This IP can be (ans is) configured with small block size.
> > > (note, that I am not saying about runtime HW configuration)
> > > 
> > > And there is opportunity what we can't use sg_list directly and
> > > need
> > > to
> > > split sg_list to a smaller chunks.
> > 
> > That's what I have referred quite ago. The driver should provide an
> > interface to tell potential caller what maximum block (number of
> > items
> > with given bus width) it supports.
> > 
> > We have struct dma_parms in struct device, but what we actually need
> > is
> > to support similar on per channel basis in DMAengine framework.
> > 
> > So, instead of working around this I recommend either to implement
> > it
> > properly or rely on the fact that in the future someone eventually
> > does that for you.
> > 
> > Each driver which has this re-splitting mechanism should be cleaned
> > up and refactored.
> 
> I still can't see any pros of this implementation.
> There is no performance profit: we anyway need to re-splitt sg_list
> (but now in dma-user driver instead of dma driver)

There is, you seems don't see it.

Currently:
 User:
  prepares sg-list

 DMA driver:
  a) iterates over it, and
  b) if sg_len is bigger than block it re-splits it.

New approach:

 User:
  a) gets DMA channel and its properties
  b) prepares sg-list taking into consideration block size

 DMA driver:
  a) uses the given sg-list and for sake of simplicity bails out if
something wrong with it

So, it means in some cases (where entry is big enough) we have to
prepare list *and* re-split it. It's really performance consuming (like
UART case where buffer is small enough and latency like above matters).

> If we want to use same descriptors several times we just can use
> DMA_CTRL_REUSE option - the descriptors will be created one time and
> re-splitting will be сompleted only one time.

There are two type of descriptors: SW and HW. That flag about SW
descriptor, so, it in most cases has nothing to do with the actual entry
size.

> But there are cons of this implementation:
> we need to implement re-splitting mechanism in each place we use dma
> instead of one dma driver. So there are more places for bugs and
> etc...

No, you completely missed the point.

With new approach we do the preparation only once per descriptor /
transfer and in one place where the sg-list is created.

> > > > Better not to pretend that it has been processed successfully.
> > > > Don't
> > > > call callback on it and set its status to DMA_ERROR (that's why
> > > > descriptors in many drivers have dma_status field). When user
> > > > asks for
> > > > status (using cookie) the saved value would be returned until
> > > > descriptor
> > > > is active.
> > > > 
> > > > Do you have some other workflow in mind?
> > > 
> > > Hmm...
> > > Do you mean I should left error descriptors in desc_issued list
> > > or I should create another list (like desc_error) in my driver and
> > > move
> > > error descriptors to desc_error list?
> > > 
> > > And when exactly should I free error descriptors?
> > 
> > See below.
> > 
> > > I checked hsu/hsu.c dma driver implementation:
> > >    vdma descriptor is deleted from desc_issued list when transfer
> > >    starts. When descriptor marked as error descriptor
> > >    vchan_cookie_complete isn't called for this descriptor. And
> > > this
> > >    descriptor isn't placed in any list. So error descriptors
> > > *never*
> > >    will be freed.
> > >    I don't actually like this approach.
> > 
> > Descriptor is active until terminate_all() is called or new
> > descriptor
> > is supplied. So, the caller has a quite time to check on it.
> > 
> > So, what's wrong on it by your opinion?
> 
> Hmm, this looks OK. (In my example (hsu/hsu.c driver) error
> descriptors
> are not freed even after terminate_all is called)

If it's active it will be freed.
Otherwise caller should check somewhere that descriptor fails.

But actually this is fragile and we need to monitor failed descriptors.
Thanks for reporting.

> 
> > Of course, if you want to keep by some reason (should be stated what
> > the reason in comment) erred descriptors, you can do that.
> 
> So, I'll create desc_error list and store failed descriptors in this
> list until terminate_all() is called.
> Is it OK implementation?

Nope, we need to amend virt-chan API for that. I'm on it. Will send a
series soon.

> There is a simple reason:
> I had to do same actions in probe/remove as in
> runtime_resume/runtime_suspend.
> (like enabling clock, enabling dma)

> If my driver is build with RUNTIME_PM this actions will be
> automatically handled by runtime pm (clock and dma will be enabled
> before using and disabled after using).
> Otherwise, if my driver is build without RUNTIME_PM clock and dma will
> be enabled only one time - when ->probe() is called.
> So I use runtime_resume callback directly for this purpose (because if
> my driver is build without RUNTIME_PM this callback wiil not be called
> at all)

Okay, The best way to do that is to create functions which take struct
chip and do that. Re-use them in runtime PM hooks.

But you still need to learn a bit about runtime PM. There is no harm to
call clk_enable() twice in a raw if you guarantee you do the opposite
(twice call clk_disable()) on tear down.

Also I would reconsider clock (un)preparation in those hooks. Why do you
need that part? It's resource consuming.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* [PATCH v3 0/2] of: Add unit tests for applying overlays
From: frowand.list-Re5JQEeQqe8AvxtiuMwx3w @ 2017-04-25 18:30 UTC (permalink / raw)
  To: Rob Herring, stephen.boyd-QSEj5FYQhm4dnm+yROfE0A,
	mmarek-IBi9RG/b67k
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-kbuild-u79uwXL29TY76Z2rM5mHXA

From: Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>

Existing overlay unit tests examine individual pieces of the overlay
code.  The new tests target the entire process of applying an overlay.

Changes from v2:
  - of_private.h: move __unflatten_device_tree() outside
    #ifdef CONFIG_OF_UNITTEST
  - unittest.c: move overlay declaration macros outside #ifdef CONFIG_OF_OVERLAY
  - unittest.c: make overlay_info overlays[] static
  - unittest.c: remove extra blank line

Changes from v1:
  - Move overlay base dtb unflattening into unittest.c.  Call from fdt.c.
  - Clarify file and variable names, 'overlay_test_' instead of 'ot_'
  - Use proper naming convention for node names.
  - A few added comments.
  - Improve error messages in the new tests.

Frank Rowand (2):
  of: support dtc compiler flags for overlays
  of: Add unit tests for applying overlays

 drivers/of/fdt.c                                 |  14 +-
 drivers/of/of_private.h                          |  12 +
 drivers/of/unittest-data/Makefile                |  17 +-
 drivers/of/unittest-data/overlay.dts             |  53 ++++
 drivers/of/unittest-data/overlay_bad_phandle.dts |  20 ++
 drivers/of/unittest-data/overlay_base.dts        |  80 ++++++
 drivers/of/unittest.c                            | 317 +++++++++++++++++++++++
 scripts/Makefile.lib                             |   2 +
 8 files changed, 507 insertions(+), 8 deletions(-)
 create mode 100644 drivers/of/unittest-data/overlay.dts
 create mode 100644 drivers/of/unittest-data/overlay_bad_phandle.dts
 create mode 100644 drivers/of/unittest-data/overlay_base.dts

-- 
Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v3 1/2] of: support dtc compiler flags for overlays
From: frowand.list @ 2017-04-25 18:30 UTC (permalink / raw)
  To: Rob Herring, stephen.boyd, mmarek; +Cc: devicetree, linux-kernel, linux-kbuild
In-Reply-To: <1493145056-16442-1-git-send-email-frowand.list@gmail.com>

From: Frank Rowand <frank.rowand@sony.com>

The dtc compiler version that adds initial support was available
in 4.11-rc1.  Add the ability to set the dtc compiler flags needed
by overlays.

Signed-off-by: Frank Rowand <frank.rowand@sony.com>
---
 scripts/Makefile.lib | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..0bbec480d323 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -283,6 +283,8 @@ ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
 DTC_FLAGS += -Wno-unit_address_vs_reg
 endif
 
+DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
+
 # Generate an assembly file to wrap the output of the device tree compiler
 quiet_cmd_dt_S_dtb= DTB     $@
 cmd_dt_S_dtb=						\
-- 
Frank Rowand <frank.rowand@sony.com>

^ permalink raw reply related

* [PATCH v3 2/2] of: Add unit tests for applying overlays
From: frowand.list @ 2017-04-25 18:30 UTC (permalink / raw)
  To: Rob Herring, stephen.boyd, mmarek; +Cc: devicetree, linux-kernel, linux-kbuild
In-Reply-To: <1493145056-16442-1-git-send-email-frowand.list@gmail.com>

From: Frank Rowand <frank.rowand@sony.com>

Existing overlay unit tests examine individual pieces of the overlay
code.  The new tests target the entire process of applying an overlay.

Signed-off-by: Frank Rowand <frank.rowand@sony.com>
---

There are checkpatch warnings.  I have reviewed them and feel they
can be ignored.

 drivers/of/fdt.c                                 |  14 +-
 drivers/of/of_private.h                          |  12 +
 drivers/of/unittest-data/Makefile                |  17 +-
 drivers/of/unittest-data/overlay.dts             |  53 ++++
 drivers/of/unittest-data/overlay_bad_phandle.dts |  20 ++
 drivers/of/unittest-data/overlay_base.dts        |  80 ++++++
 drivers/of/unittest.c                            | 317 +++++++++++++++++++++++
 7 files changed, 505 insertions(+), 8 deletions(-)
 create mode 100644 drivers/of/unittest-data/overlay.dts
 create mode 100644 drivers/of/unittest-data/overlay_bad_phandle.dts
 create mode 100644 drivers/of/unittest-data/overlay_base.dts

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index e5ce4b59e162..e33f7818bc6c 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -31,6 +31,8 @@
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
 
+#include "of_private.h"
+
 /*
  * of_fdt_limit_memory - limit the number of regions in the /memory node
  * @limit: maximum entries
@@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob,
  * Returns NULL on failure or the memory chunk containing the unflattened
  * device tree on success.
  */
-static void *__unflatten_device_tree(const void *blob,
-				     struct device_node *dad,
-				     struct device_node **mynodes,
-				     void *(*dt_alloc)(u64 size, u64 align),
-				     bool detached)
+void *__unflatten_device_tree(const void *blob,
+			      struct device_node *dad,
+			      struct device_node **mynodes,
+			      void *(*dt_alloc)(u64 size, u64 align),
+			      bool detached)
 {
 	int size;
 	void *mem;
@@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void)
 
 	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
 	of_alias_scan(early_init_dt_alloc_memory_arch);
+
+	unittest_unflatten_overlay_base();
 }
 
 /**
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 18bbb4517e25..de5c604f5cc4 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -55,6 +55,18 @@ static inline int of_property_notify(int action, struct device_node *np,
 }
 #endif /* CONFIG_OF_DYNAMIC */
 
+#ifdef CONFIG_OF_UNITTEST
+extern void __init unittest_unflatten_overlay_base(void);
+#else
+static inline void unittest_unflatten_overlay_base(void) {};
+#endif
+
+extern void *__unflatten_device_tree(const void *blob,
+			      struct device_node *dad,
+			      struct device_node **mynodes,
+			      void *(*dt_alloc)(u64 size, u64 align),
+			      bool detached);
+
 /**
  * General utilities for working with live trees.
  *
diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile
index 1ac5cc01d627..6e00a9c69e58 100644
--- a/drivers/of/unittest-data/Makefile
+++ b/drivers/of/unittest-data/Makefile
@@ -1,7 +1,18 @@
 obj-y += testcases.dtb.o
+obj-y += overlay.dtb.o
+obj-y += overlay_bad_phandle.dtb.o
+obj-y += overlay_base.dtb.o
 
 targets += testcases.dtb testcases.dtb.S
+targets += overlay.dtb overlay.dtb.S
+targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S
+targets += overlay_base.dtb overlay_base.dtb.S
 
-.SECONDARY: \
-	$(obj)/testcases.dtb.S \
-	$(obj)/testcases.dtb
+.PRECIOUS: \
+	$(obj)/%.dtb.S \
+	$(obj)/%.dtb
+
+# enable creation of __symbols__ node
+DTC_FLAGS_overlay := -@
+DTC_FLAGS_overlay_bad_phandle := -@
+DTC_FLAGS_overlay_base := -@
diff --git a/drivers/of/unittest-data/overlay.dts b/drivers/of/unittest-data/overlay.dts
new file mode 100644
index 000000000000..6cd7e6a0c13e
--- /dev/null
+++ b/drivers/of/unittest-data/overlay.dts
@@ -0,0 +1,53 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+
+	fragment@0 {
+		target = <&electric_1>;
+
+		__overlay__ {
+			status = "ok";
+
+			hvac_2: hvac-large-1 {
+				compatible = "ot,hvac-large";
+				heat-range = < 40 75 >;
+				cool-range = < 65 80 >;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&rides_1>;
+
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "ok";
+
+			ride@200 {
+				compatible = "ot,ferris-wheel";
+				reg = < 0x00000200 0x100 >;
+				hvac-provider = < &hvac_2 >;
+				hvac-thermostat = < 27 32 > ;
+				hvac-zones = < 12 5 >;
+				hvac-zone-names = "operator", "snack-bar";
+				spin-controller = < &spin_ctrl_1 3 >;
+				spin-rph = < 30 >;
+				gondolas = < 16 >;
+				gondola-capacity = < 6 >;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&lights_2>;
+
+		__overlay__ {
+			status = "ok";
+			color = "purple", "white", "red", "green";
+			rate = < 3 256 >;
+		};
+	};
+
+};
diff --git a/drivers/of/unittest-data/overlay_bad_phandle.dts b/drivers/of/unittest-data/overlay_bad_phandle.dts
new file mode 100644
index 000000000000..270ee885a623
--- /dev/null
+++ b/drivers/of/unittest-data/overlay_bad_phandle.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+
+	fragment@0 {
+		target = <&electric_1>;
+
+		__overlay__ {
+
+			// This label should cause an error when the overlay
+			// is applied.  There is already a phandle value
+			// in the base tree for motor-1.
+			spin_ctrl_1_conflict: motor-1 {
+				accelerate = < 3 >;
+				decelerate = < 5 >;
+			};
+		};
+	};
+};
diff --git a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts
new file mode 100644
index 000000000000..5566b27fb61a
--- /dev/null
+++ b/drivers/of/unittest-data/overlay_base.dts
@@ -0,0 +1,80 @@
+/dts-v1/;
+/plugin/;
+
+/*
+ * Base device tree that overlays will be applied against.
+ *
+ * Do not add any properties in node "/".
+ * Do not add any nodes other than "/testcase-data-2" in node "/".
+ * Do not add anything that would result in dtc creating node "/__fixups__".
+ * dtc will create nodes "/__symbols__" and "/__local_fixups__".
+ */
+
+/ {
+	testcase-data-2 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		electric_1: substation@100 {
+			compatible = "ot,big-volts-control";
+			reg = < 0x00000100 0x100 >;
+			status = "disabled";
+
+			hvac_1: hvac-medium-1 {
+				compatible = "ot,hvac-medium";
+				heat-range = < 50 75 >;
+				cool-range = < 60 80 >;
+			};
+
+			spin_ctrl_1: motor-1 {
+				compatible = "ot,ferris-wheel-motor";
+				spin = "clockwise";
+			};
+
+			spin_ctrl_2: motor-8 {
+				compatible = "ot,roller-coaster-motor";
+			};
+		};
+
+		rides_1: fairway-1 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "ot,rides";
+			status = "disabled";
+			orientation = < 127 >;
+
+			ride@100 {
+				compatible = "ot,roller-coaster";
+				reg = < 0x00000100 0x100 >;
+				hvac-provider = < &hvac_1 >;
+				hvac-thermostat = < 29 > ;
+				hvac-zones = < 14 >;
+				hvac-zone-names = "operator";
+				spin-controller = < &spin_ctrl_2 5 &spin_ctrl_2 7 >;
+				spin-controller-names = "track_1", "track_2";
+				queues = < 2 >;
+			};
+		};
+
+		lights_1: lights@30000 {
+			compatible = "ot,work-lights";
+			reg = < 0x00030000 0x1000 >;
+			status = "disabled";
+		};
+
+		lights_2: lights@40000 {
+			compatible = "ot,show-lights";
+			reg = < 0x00040000 0x1000 >;
+			status = "disabled";
+			rate = < 13 138 >;
+		};
+
+		retail_1: vending@50000 {
+			reg = < 0x00050000 0x1000 >;
+			compatible = "ot,tickets";
+			status = "disabled";
+		};
+
+	};
+};
+
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 62db55b97c10..12597ff8cfb0 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/hashtable.h>
+#include <linux/libfdt.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
@@ -1925,6 +1926,320 @@ static void __init of_unittest_overlay(void)
 static inline void __init of_unittest_overlay(void) { }
 #endif
 
+/*
+ * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
+ * in scripts/Makefile.lib
+ */
+
+#define OVERLAY_INFO_EXTERN(name) \
+	extern uint8_t __dtb_##name##_begin[]; \
+	extern uint8_t __dtb_##name##_end[]
+
+#define OVERLAY_INFO(name, expected) \
+{	.dtb_begin	 = __dtb_##name##_begin, \
+	.dtb_end	 = __dtb_##name##_end, \
+	.expected_result = expected, \
+}
+
+struct overlay_info {
+	uint8_t		   *dtb_begin;
+	uint8_t		   *dtb_end;
+	void		   *data;
+	struct device_node *np_overlay;
+	int		   expected_result;
+	int		   overlay_id;
+};
+
+OVERLAY_INFO_EXTERN(overlay_base);
+OVERLAY_INFO_EXTERN(overlay);
+OVERLAY_INFO_EXTERN(overlay_bad_phandle);
+
+#ifdef CONFIG_OF_OVERLAY
+
+/* order of entries is hard-coded into users of overlays[] */
+static struct overlay_info overlays[] = {
+	OVERLAY_INFO(overlay_base, -9999),
+	OVERLAY_INFO(overlay, 0),
+	OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
+	{}
+};
+
+static struct device_node *overlay_base_root;
+
+/*
+ * Create base device tree for the overlay unittest.
+ *
+ * This is called from very early boot code.
+ *
+ * Do as much as possible the same way as done in __unflatten_device_tree
+ * and other early boot steps for the normal FDT so that the overlay base
+ * unflattened tree will have the same characteristics as the real tree
+ * (such as having memory allocated by the early allocator).  The goal
+ * is to test "the real thing" as much as possible, and test "test setup
+ * code" as little as possible.
+ *
+ * Have to stop before resolving phandles, because that uses kmalloc.
+ */
+void __init unittest_unflatten_overlay_base(void)
+{
+	struct overlay_info *info;
+	u32 data_size;
+	u32 size;
+
+	info = &overlays[0];
+
+	if (info->expected_result != -9999) {
+		pr_err("No dtb 'overlay_base' to attach\n");
+		return;
+	}
+
+	data_size = info->dtb_end - info->dtb_begin;
+	if (!data_size) {
+		pr_err("No dtb 'overlay_base' to attach\n");
+		return;
+	}
+
+	size = fdt_totalsize(info->dtb_begin);
+	if (size != data_size) {
+		pr_err("dtb 'overlay_base' header totalsize != actual size");
+		return;
+	}
+
+	info->data = early_init_dt_alloc_memory_arch(size,
+					     roundup_pow_of_two(FDT_V17_SIZE));
+	if (!info->data) {
+		pr_err("alloc for dtb 'overlay_base' failed");
+		return;
+	}
+
+	memcpy(info->data, info->dtb_begin, size);
+
+	__unflatten_device_tree(info->data, NULL, &info->np_overlay,
+				early_init_dt_alloc_memory_arch, true);
+	overlay_base_root = info->np_overlay;
+}
+
+/*
+ * The purpose of of_unittest_overlay_data_add is to add an
+ * overlay in the normal fashion.  This is a test of the whole
+ * picture, instead of testing individual elements.
+ *
+ * A secondary purpose is to be able to verify that the contents of
+ * /proc/device-tree/ contains the updated structure and values from
+ * the overlay.  That must be verified separately in user space.
+ *
+ * Return 0 on unexpected error.
+ */
+static int __init overlay_data_add(int onum)
+{
+	struct overlay_info *info;
+	int k;
+	int ret;
+	u32 size;
+	u32 size_from_header;
+
+	for (k = 0, info = overlays; info; info++, k++) {
+		if (k == onum)
+			break;
+	}
+	if (onum > k)
+		return 0;
+
+	size = info->dtb_end - info->dtb_begin;
+	if (!size) {
+		pr_err("no overlay to attach, %d\n", onum);
+		ret = 0;
+	}
+
+	size_from_header = fdt_totalsize(info->dtb_begin);
+	if (size_from_header != size) {
+		pr_err("overlay header totalsize != actual size, %d", onum);
+		return 0;
+	}
+
+	/*
+	 * Must create permanent copy of FDT because of_fdt_unflatten_tree()
+	 * will create pointers to the passed in FDT in the EDT.
+	 */
+	info->data = kmemdup(info->dtb_begin, size, GFP_KERNEL);
+	if (!info->data) {
+		pr_err("unable to allocate memory for data, %d\n", onum);
+		return 0;
+	}
+
+	of_fdt_unflatten_tree(info->data, NULL, &info->np_overlay);
+	if (!info->np_overlay) {
+		pr_err("unable to unflatten overlay, %d\n", onum);
+		ret = 0;
+		goto out_free_data;
+	}
+	of_node_set_flag(info->np_overlay, OF_DETACHED);
+
+	ret = of_resolve_phandles(info->np_overlay);
+	if (ret) {
+		pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum);
+		goto out_free_np_overlay;
+	}
+
+	ret = of_overlay_create(info->np_overlay);
+	if (ret < 0) {
+		pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum);
+		goto out_free_np_overlay;
+	} else {
+		info->overlay_id = ret;
+		ret = 0;
+	}
+
+	pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret);
+
+	goto out;
+
+out_free_np_overlay:
+	/*
+	 * info->np_overlay is the unflattened device tree
+	 * It has not been spliced into the live tree.
+	 */
+
+	/* todo: function to free unflattened device tree */
+
+out_free_data:
+	kfree(info->data);
+
+out:
+	return (ret == info->expected_result);
+}
+
+/*
+ * The purpose of of_unittest_overlay_high_level is to add an overlay
+ * in the normal fashion.  This is a test of the whole picture,
+ * instead of individual elements.
+ *
+ * The first part of the function is _not_ normal overlay usage; it is
+ * finishing splicing the base overlay device tree into the live tree.
+ */
+static __init void of_unittest_overlay_high_level(void)
+{
+	struct device_node *last_sibling;
+	struct device_node *np;
+	struct device_node *of_symbols;
+	struct device_node *overlay_base_symbols;
+	struct device_node **pprev;
+	struct property *prop;
+	int ret;
+
+	if (!overlay_base_root) {
+		unittest(0, "overlay_base_root not initialized\n");
+		return;
+	}
+
+	/*
+	 * Could not fixup phandles in unittest_unflatten_overlay_base()
+	 * because kmalloc() was not yet available.
+	 */
+	of_resolve_phandles(overlay_base_root);
+
+	/*
+	 * do not allow overlay_base to duplicate any node already in
+	 * tree, this greatly simplifies the code
+	 */
+
+	/*
+	 * remove overlay_base_root node "__local_fixups", after
+	 * being used by of_resolve_phandles()
+	 */
+	pprev = &overlay_base_root->child;
+	for (np = overlay_base_root->child; np; np = np->sibling) {
+		if (!of_node_cmp(np->name, "__local_fixups__")) {
+			*pprev = np->sibling;
+			break;
+		}
+		pprev = &np->sibling;
+	}
+
+	/* remove overlay_base_root node "__symbols__" if in live tree */
+	of_symbols = of_get_child_by_name(of_root, "__symbols__");
+	if (of_symbols) {
+		/* will have to graft properties from node into live tree */
+		pprev = &overlay_base_root->child;
+		for (np = overlay_base_root->child; np; np = np->sibling) {
+			if (!of_node_cmp(np->name, "__symbols__")) {
+				overlay_base_symbols = np;
+				*pprev = np->sibling;
+				break;
+			}
+			pprev = &np->sibling;
+		}
+	}
+
+	for (np = overlay_base_root->child; np; np = np->sibling) {
+		if (of_get_child_by_name(of_root, np->name)) {
+			unittest(0, "illegal node name in overlay_base %s",
+				np->name);
+			return;
+		}
+	}
+
+	/*
+	 * overlay 'overlay_base' is not allowed to have root
+	 * properties, so only need to splice nodes into main device tree.
+	 *
+	 * root node of *overlay_base_root will not be freed, it is lost
+	 * memory.
+	 */
+
+	for (np = overlay_base_root->child; np; np = np->sibling)
+		np->parent = of_root;
+
+	mutex_lock(&of_mutex);
+
+	for (np = of_root->child; np; np = np->sibling)
+		last_sibling = np;
+
+	if (last_sibling)
+		last_sibling->sibling = overlay_base_root->child;
+	else
+		of_root->child = overlay_base_root->child;
+
+	for_each_of_allnodes_from(overlay_base_root, np)
+		__of_attach_node_sysfs(np);
+
+	if (of_symbols) {
+		for_each_property_of_node(overlay_base_symbols, prop) {
+			ret = __of_add_property(of_symbols, prop);
+			if (ret) {
+				unittest(0,
+					 "duplicate property '%s' in overlay_base node __symbols__",
+					 prop->name);
+				return;
+			}
+			ret = __of_add_property_sysfs(of_symbols, prop);
+			if (ret) {
+				unittest(0,
+					 "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
+					 prop->name);
+				return;
+			}
+		}
+	}
+
+	mutex_unlock(&of_mutex);
+
+
+	/* now do the normal overlay usage test */
+
+	unittest(overlay_data_add(1),
+		 "Adding overlay 'overlay' failed\n");
+
+	unittest(overlay_data_add(2),
+		 "Adding overlay 'overlay_bad_phandle' failed\n");
+}
+
+#else
+
+static inline __init void of_unittest_overlay_high_level(void) {}
+
+#endif
+
 static int __init of_unittest(void)
 {
 	struct device_node *np;
@@ -1962,6 +2277,8 @@ static int __init of_unittest(void)
 	/* Double check linkage after removing testcase data */
 	of_unittest_check_tree_linkage();
 
+	of_unittest_overlay_high_level();
+
 	pr_info("end of unittest - %i passed, %i failed\n",
 		unittest_results.passed, unittest_results.failed);
 
-- 
Frank Rowand <frank.rowand@sony.com>


^ permalink raw reply related

* [RESEND][PATCH V2 1/4] mfd: Add ROHM BD9571MWV-M PMIC DT bindings
From: Marek Vasut @ 2017-04-25 18:32 UTC (permalink / raw)
  To: linux-renesas-soc
  Cc: lee.jones, Marek Vasut, devicetree, Rob Herring,
	Geert Uytterhoeven

Add DT bindings for the ROHM BD9571MWV-M PMIC. This PMIC has
the following features:
- multiple voltage monitors for 1V8, 2V5, 3V3 voltage rail
- one voltage regulator for DVFS
- two GPIOs

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: devicetree@vger.kernel.org
Cc: Rob Herring <robh@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: linux-renesas-soc@vger.kernel.org
---
V2: - Drop the compatible = "regulator-fixed" from the binding example,
      it should not be there.
    - List the VD09 regulator
---
 .../devicetree/bindings/mfd/bd9571mwv.txt          | 49 ++++++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/bd9571mwv.txt

diff --git a/Documentation/devicetree/bindings/mfd/bd9571mwv.txt b/Documentation/devicetree/bindings/mfd/bd9571mwv.txt
new file mode 100644
index 000000000000..ce24231edd7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/bd9571mwv.txt
@@ -0,0 +1,49 @@
+* ROHM BD9571MWV Power Management Integrated Circuit (PMIC) bindings
+
+Required properties:
+ - compatible		: Should be "rohm,bd9571mwv".
+ - reg			: I2C slave address.
+ - interrupt-parent	: Phandle to the parent interrupt controller.
+ - interrupts		: The interrupt line the device is connected to.
+ - interrupt-controller	: Marks the device node as an interrupt controller.
+ - #interrupt-cells	: The number of cells to describe an IRQ, should be 2.
+			    The first cell is the IRQ number.
+			    The second cell is the flags, encoded as trigger
+			    masks from ../interrupt-controller/interrupts.txt.
+ - gpio-controller      : Marks the device node as a GPIO Controller.
+ - #gpio-cells          : Should be two.  The first cell is the pin number and
+                            the second cell is used to specify flags.
+                            See ../gpio/gpio.txt for more information.
+ - regulators:          : List of child nodes that specify the regulator
+                            initialization data. Child nodes must be named
+                            after their hardware counterparts:
+			     - vd09
+			     - vd18
+			     - vd25
+			     - vd33
+			     - dvfs
+			    Each child node is defined using the standard
+			    binding for regulators.
+
+Example:
+
+	pmic: bd9571mwv@30 {
+		compatible = "rohm,bd9571mwv";
+		reg = <0x30>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		regulators {
+			dvfs: dvfs {
+				regulator-name = "dvfs";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1030000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next] dt-bindings: mdio: Clarify binding document
From: Florian Fainelli @ 2017-04-25 18:33 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: rogerq-l0cyMroinI0, andrew-g2DYL2Zd6BY,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	nsekhar-l0cyMroinI0, jsarha-l0cyMroinI0,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
	Florian Fainelli, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list

The described GPIO reset property is applicable to *all* child PHYs. If
we have one reset line per PHY present on the MDIO bus, these
automatically become properties of the child PHY nodes.

Finally, indicate how the RESET pulse width must be defined, which is
the maximum value of all individual PHYs RESET pulse widths determined
by reading their datasheets.

Fixes: 69226896ad63 ("mdio_bus: Issue GPIO RESET to PHYs.")
Signed-off-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 Documentation/devicetree/bindings/net/mdio.txt | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mdio.txt b/Documentation/devicetree/bindings/net/mdio.txt
index 4ffbbacebda1..96a53f89aa6e 100644
--- a/Documentation/devicetree/bindings/net/mdio.txt
+++ b/Documentation/devicetree/bindings/net/mdio.txt
@@ -3,13 +3,17 @@ Common MDIO bus properties.
 These are generic properties that can apply to any MDIO bus.
 
 Optional properties:
-- reset-gpios: List of one or more GPIOs that control the RESET lines
-  of the PHYs on that MDIO bus.
-- reset-delay-us: RESET pulse width in microseconds as per PHY datasheet.
+- reset-gpios: One GPIO that control the RESET lines of all PHYs on that MDIO
+  bus.
+- reset-delay-us: RESET pulse width in microseconds.
 
 A list of child nodes, one per device on the bus is expected. These
 should follow the generic phy.txt, or a device specific binding document.
 
+The 'reset-delay-us' indicates the RESET signal pulse width in microseconds and
+applies to all PHY devices. It must therefore be appropriately determined based
+on all PHY requirements (maximum value of all per-PHY RESET pulse widths).
+
 Example :
 This example shows these optional properties, plus other properties
 required for the TI Davinci MDIO driver.
@@ -21,7 +25,7 @@ required for the TI Davinci MDIO driver.
 		#size-cells = <0>;
 
 		reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
-		reset-delay-us = <2>;   /* PHY datasheet states 1us min */
+		reset-delay-us = <2>;
 
 		ethphy0: ethernet-phy@1 {
 			reg = <1>;
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox